了解 MSDN 中的 NetworkStream.EndRead() 示例

本文关键字:示例 EndRead NetworkStream MSDN 中的 了解 | 更新日期: 2023-09-27 18:33:23

我试图理解 NetworkStream.EndRead(( 的 MSDN 示例。有些部分我不明白。

所以这是一个例子(从MSDN复制(:

// Example of EndRead, DataAvailable and BeginRead.
public static void myReadCallBack(IAsyncResult ar ){
    NetworkStream myNetworkStream = (NetworkStream)ar.AsyncState;
    byte[] myReadBuffer = new byte[1024];
    String myCompleteMessage = "";
    int numberOfBytesRead;
    numberOfBytesRead = myNetworkStream.EndRead(ar);
    myCompleteMessage = 
        String.Concat(myCompleteMessage, Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));    
    // message received may be larger than buffer size so loop through until you have it all.
    while(myNetworkStream.DataAvailable){
        myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, 
                                               new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack), 
                                                   myNetworkStream);  
    }
    // Print out the received message to the console.
    Console.WriteLine("You received the following message : " +
                                myCompleteMessage);
}

它使用 BeginRead(( 和 EndRead(( 从网络流中异步读取。整个事情都是通过调用来调用的

myNetworkStream.BeginRead(someBuffer, 0, someBuffer.Length, new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream);  

其他地方(未在示例中显示(。

我认为它应该做的是将从NetworkStream收到的整个消息打印在单个WriteLine(示例末尾的那个(中。请注意,该字符串称为 myCompleteMessage

现在,当我查看实现时,我的理解出现了一些问题。

首先:该示例分配了一个新的方法-本地缓冲区myReadBuffer。然后调用 EndStream((,它将收到的消息写入提供 BeginRead(( 的缓冲区。这不是刚刚分配的myReadBuffer。网络流应该如何知道它?因此,在下一行中numberOfBytesRead来自空缓冲区的字节将附加到myCompleteMessage 。其中当前值"" .在最后一行中,这条消息由许多''0' s组成,并打印有 Console.WriteLine

这对我来说没有任何意义。

我不明白的第二件事是while循环。

BeginRead是一个异步调用。因此不会立即读取任何数据。因此,据我了解,while 循环应该运行一段时间,直到实际执行一些异步调用并从流中读取,以便不再有可用的数据。该文档没有说BeginRead立即将可用数据的某些部分标记为正在读取,因此我不希望它这样做。

这个例子并没有提高我对这些方法的理解。这个例子是错的还是我的理解错了(我期望后者(?此示例如何工作?

了解 MSDN 中的 NetworkStream.EndRead() 示例

我认为围绕 BeginRead 的 while 循环不应该存在。您不希望在 EndRead 完成之前执行多个 BeginRead。此外,需要在 BeginRead 外部指定缓冲区,因为每个数据包/缓冲区可能使用多个读取。

您需要考虑一些事情,例如我的消息/块有多长(固定大小(。我应该在它前面加上一个长度吗?(大小可变( <datalength><data><datalength><data>

不要忘记它是一个流连接,因此可以在一次读取中读取多个/部分消息/数据包。

伪示例:

int bytesNeeded;
int bytesRead;
public void Start()
{
    bytesNeeded = 40; // u need to know how much bytes you're needing
    bytesRead = 0;
    BeginReading();
}
public void BeginReading()
{
    myNetworkStream.BeginRead(
        someBuffer, bytesRead, bytesNeeded - bytesRead, 
        new AsyncCallback(EndReading), 
        myNetworkStream);
}
public void EndReading(IAsyncResult ar)
{
    numberOfBytesRead = myNetworkStream.EndRead(ar);
    if(numberOfBytesRead == 0)
    {
        // disconnected
        return;
    }
    bytesRead += numberOfBytesRead;
    if(bytesRead == bytesNeeded)
    {
        // Handle buffer
        Start();
    }
    else
        BeginReading();
}