Как узнать, когда заканчивается чтение асинхронного сокета? - PullRequest
2 голосов
/ 21 февраля 2012

У меня есть метод асинхронного чтения ...

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);
        }
    }

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

Спасибо!

Ответы [ 2 ]

4 голосов
/ 21 февраля 2012

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

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

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

0 голосов
/ 21 февраля 2012

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

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

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

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