【问题标题】:Will writing bytes to a TcpClient's NetworkStream before the remote is set up to read discard bytes?在远程设置为读取丢弃字节之前将字节写入 TcpClient 的 NetworkStream 吗?
【发布时间】:2019-05-07 06:48:53
【问题描述】:

我正在设置一些套接字,遇到了一些奇怪的行为,想知道这是否是预期的。

我在套接字的每一侧都有两个线程。编写器(每侧一个)只是从队列中获取消息,将它们序列化,然后写入字节。读取器(每侧一个)读取我的自定义协议的标头和正文,反序列化消息并触发事件。

够简单吧?

我感兴趣的奇怪行为发生在客户端连接到服务器然后立即写入消息时。客户端可能非常快,以至于在客户端发送消息时服务器还没有启动它的读取线程。如果发生这种情况,那么服务器永远不会收到消息。读取线程实际调用 Read() 后发送的消息被成功接收和处理。

这是预期的行为吗?是否预期在读取另一端的任何内容之前写入套接字的字节将被 Read() 忽略?

【问题讨论】:

    标签: c# sockets tcp


    【解决方案1】:

    不,TCP 接收缓冲区是在三次握手期间创建的,第一次读取将看到到目前为止在连接上发送的所有数据。

    这是假设您有一个称职的 TCP/IP 实现。如果您的连接的另一端是嵌入式设备上的最小手动 TCP 库,那么所有的赌注都没有了。

    更有可能的是,一次阅读收到了多条消息,而收件人忘记了处理第一条之后的任何消息。 TCP 不保留消息边界。您必须在协议中包含足够的长度和/或定界信息才能恢复这些边界。而且您必须处理在读取缓冲区中获得的消息少于或多于一条。

    【讨论】:

    • 双方都是.NET。 (我在一些单元测试中运行它)标题是固定长度并包括正文长度,所以我虽然可以很好地控制字节的读取方式。读取线程接受来自 Read() 方法的输入,因此它可以在收到部分消息后继续读取。 NetworkStream 是否会使这一切复杂化,还是我应该只使用 TcpClient 的 Socket?
    • 如果我在写第一条消息之前添加一个睡眠,一切正常。如果所有字节都按预期累积在缓冲区中,我认为睡眠应该是无关紧要的。
    • EndConnect 成功完成后,我也会立即写入套接字。套接字是否需要额外的时间才能准备好?
    猜你喜欢
    • 2017-06-24
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    相关资源
    最近更新 更多