我怎么知道异步套接字读取何时结束?

时间:2012-02-21 18:29:32

标签: c# sockets networking asynchronous

我有一个异步读取方法......

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 个答案:

答案 0 :(得分:4)

您不应该依赖TCP缓冲区中的内容。您必须将传入的字节作为流处理。你不能真正知道它是否完整。上面只有一层可以知道消息何时完成。

实施例: 如果您读取HTTP响应,HTTP标头将包含HTTP正文中的字节计数。所以你知道要阅读多少。

如果数据遵循某个协议并且您解释它,您只知道读取多少。想象一下,你通过套接字收到一个文件。您将收到的第一件事是文件大小。没有它,你永远不会知道读多少。

答案 1 :(得分:0)

您应该使您的消息符合特定格式,以便您可以区分它们的开始和结束时间。即使它是数据流,也应该以数据包的形式发送。

一种选择是先发送消息长度然后知道预期的数据量。但问题是,如果你松开同步,你永远无法恢复,你永远不会知道什么是消息长度,它的内容是什么。最好使用一些特殊的标记序列来了解消息何时开始。它不是100%的错误证明(序列可能出现在数据中),但肯定有帮助,并允许从同步松散恢复。当从像socket这样的二进制流中读取时,这一点尤其重要。

即使是古老的RS232串行协议也有它的帧和停止位,以便在获得所有数据时知道。