我有一个异步读取方法......
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。我怎么说,这是该消息的结束并将数据传递给调度程序,同时保持套接字打开以接受新消息。
谢谢!
答案 0 :(得分:4)
您不应该依赖TCP缓冲区中的内容。您必须将传入的字节作为流处理。你不能真正知道它是否完整。上面只有一层可以知道消息何时完成。
实施例: 如果您读取HTTP响应,HTTP标头将包含HTTP正文中的字节计数。所以你知道要阅读多少。
如果数据遵循某个协议并且您解释它,您只知道读取多少。想象一下,你通过套接字收到一个文件。您将收到的第一件事是文件大小。没有它,你永远不会知道读多少。
答案 1 :(得分:0)
您应该使您的消息符合特定格式,以便您可以区分它们的开始和结束时间。即使它是数据流,也应该以数据包的形式发送。
一种选择是先发送消息长度然后知道预期的数据量。但问题是,如果你松开同步,你永远无法恢复,你永远不会知道什么是消息长度,它的内容是什么。最好使用一些特殊的标记序列来了解消息何时开始。它不是100%的错误证明(序列可能出现在数据中),但肯定有帮助,并允许从同步松散恢复。当从像socket这样的二进制流中读取时,这一点尤其重要。
即使是古老的RS232串行协议也有它的帧和停止位,以便在获得所有数据时知道。