【问题标题】:How do I know when an asynchronous socket read ends?我如何知道异步套接字读取何时结束?
【发布时间】:2012-02-21 18:29:32
【问题描述】:

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

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。怎么说呢,这是该消息的结尾并将数据传递给调度程序,同时保持套接字打开以接受新消息。

谢谢!

【问题讨论】:

    标签: c# sockets networking asynchronous


    【解决方案1】:

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

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

    您只有在数据遵循特定协议并对其进行解释时才知道要读取多少。想象一下,您通过套接字接收到一个文件。您将收到的第一件事是文件大小。没有它,您将永远不知道该读多少。

    【讨论】:

    • 所以我需要在消息的乞求时发送一​​个消息长度来告诉消息何时完成?
    • 正是如此。否则,您将拥有永无止境的数据流,例如互联网广播流中的音频流。
    【解决方案2】:

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

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

    即使是古老的 RS232 串行协议也有它的帧和停止位来知道你什么时候得到了所有的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-27
      • 1970-01-01
      • 2022-11-11
      • 2011-06-07
      相关资源
      最近更新 更多