2013-10-01 5 views
5

Я попытался понять пример MSDN для NetworkStream.EndRead(). Есть некоторые части, которые я не понимаю.Понимание 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 -loop.

BeginRead - это асинхронный вызов. Поэтому данные сразу не считываются. Итак, как я понимаю, цикл while должен выполняться довольно долго, пока какой-либо асинхронный вызов не будет выполнен и не будет прочитан из потока, так что данных больше нет. В документации не говорится, что BeginRead сразу же отмечает, что часть доступных данных считывается, поэтому я не ожидаю, что это будет сделано.

Этот пример не улучшает мое понимание этих методов. Является ли этот пример неправильным или мое понимание неверно (я ожидаю последнего)? Как работает этот пример?

+2

пример просто неправильно. Действительно неправильно. –

ответ

5

Я думаю, что в то время как петля вокруг BeginRead не должна быть там. Вы не хотите выполнять BeginRead больше, чем до завершения EndRead. Кроме того, буфер необходимо указывать вне 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(); 
} 
+0

да, это имеет для меня больше смысла – jsf

Смежные вопросы