2012-02-21 2 views
1

У меня есть асинхронный метод чтения ...Как узнать, когда заканчивается чтение асинхронного сокета?

private void read(IAsyncResult ar) { 
     //Get the Server State Object 
     ServerState state = (ServerState)ar.AsyncState; 

     //read from the socket 
     int readCount = state.socket.EndReceive(ar); 

     //check if reading is done, move on if so, trigger another read if not 
     if (readCount > 0) { 
      //purge the buffer and start another read 
      state.purgeBuffer(); 
      state.socket.BeginReceive(state.buffer, 0, ServerState.bufferSize, 0, new AsyncCallback(read), state); 
     } 
     else { 
      //all bytes have been read, dispatch the message 
      dispatch(state); 
     } 
    } 

Проблема, которую я имею, что чтения только 0, если соединение закрывается. Как я могу сказать, это конец этого сообщения и передать данные диспетчеру, оставив сокет открытым, чтобы принимать новые сообщения.

Спасибо!

ответ

4

Вы не должны полагаться на то, что находится в буфере TCP. Вы должны обрабатывать входящие байты как поток где-нибудь. Вы не можете знать, все ли это. Только один уровень выше может знать, когда сообщение завершено.

Пример: Если вы читаете ответы HTTP, HTTP-заголовок будет содержать количество байтов, которое находится в теле HTTP. Значит, ты умеешь читать.

Вы знаете только, сколько нужно читать, если данные соответствуют определенному протоколу и вы его интерпретируете. Представьте, что вы получаете файл через сокет. Первое, что вы получили, это размер файла. Без этого вы никогда не узнаете, сколько читать.

+0

Так что мне нужно отправить длину сообщения при попрошайничестве сообщения, чтобы сообщить, когда сообщение будет завершено? – Dabloons

+0

Именно это. Без этого у вас есть бесконечный поток данных, таких как аудиопотоки в потоках интернет-радио. – BlueM

0

Вы должны сделать ваши сообщения подходящими для определенного формата, чтобы вы могли различать, когда они начинаются и когда заканчиваются. Даже если это поток данных, он должен быть отправлен в пакеты.

Один из вариантов - сначала отправить длину сообщения, а затем вы знаете, сколько данных ожидать. Но проблема в том, что если вы потеряете синхронизацию, вы никогда не сможете ее восстановить, и вы никогда не узнаете, что такое длина сообщения и каков его контент. Полезно использовать некоторую специальную последовательность маркировки, чтобы знать, когда начинается сообщение. Это не 100% -ное доказательство ошибок (последовательность может появляться в данных), но, безусловно, помогает и позволяет восстанавливаться после синхронизации. Это особенно важно при чтении из двоичного потока, такого как сокет.

Даже древний последовательный протокол RS232 имел свой кадр и бит остановки, чтобы знать, когда вы получили все данные.

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