2013-10-01 51 views
5

我试图了解NetworkStream.EndRead()的MSDN示例。有些部分我不明白。了解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'组成的消息印有Console.WriteLine

这对我没有任何意义。

我不明白的第二件事是while -loop。

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

这个例子并没有改善我对这些方法的理解。这个例子是错误的还是我的理解错误(我期望后者)?这个例子如何工作?

+2

的例子是错误的。真的错了。 –

回答

5

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

你需要考虑一些事情,比如我的信息/信息块有多长时间(固定大小)。我应该用一个长度作为它的前缀。 (可变大小)<datalength><data><datalength><data>

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

伪例如:

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(); 
} 
+0

是的,这对我来说更有意义 – jsf