【问题标题】:Writing to TcpClient and NetworkStream写入 TcpClient 和 NetworkStream
【发布时间】:2012-07-14 07:17:31
【问题描述】:

我对如何在 .net 中使用 tcp 流感到有些困惑。 现在,当我想写 40 字节时,我将其写入内存流,然后调用 ToArray() 并将内存流写入网络流 + 刷新。

在服务器端,我使用 Read(buf, 0, len) 并检查长度是否完全符合我的预期。我这样做很愚蠢吗?我可以写尽可能少的字节,然后在我准备好阅读时刷新吗?

当我 Read() 时,我总是会得到我期望的长度吗? (假设应用程序是正确的并且没有发生错误)它会阻塞直到我的尺寸准备好?我不需要循环读取并构建我的缓冲区,对吗?假设我期待像 10k 或更高的大尺寸,然后我需要建立我的缓冲区吗?

【问题讨论】:

    标签: .net tcpclient


    【解决方案1】:

    我知道前面的两个答案都在告诉你,但我会重复它们并添加一些我的东西:如果在后续发送之间有足够的时间,它会按照你的预期工作,这可能会让你相信它真的是这样工作的。但事实并非如此。

    TCP 很容易被想象成一根你在一端装满水的水管。添加新的一杯水并不能告诉您它的大小,只是向管道中添加更多的水。

    因此,您需要在流中实现自己的“消息传递”或“打包”。

    不过,还不错。 Stream 是健壮的,所以如果你在数据前面加上它的长度,你就可以让它工作——只需在接收端创建某种“数据包收集机制”——有一些缓冲区可以保存部分数据包数据,直到你得到你需要的一切。

    编辑:

    解决您的问题:

    • Flush() 在这里无关紧要。
    • 你不会得到你期望的大小。您将获得 0 到运输途中剩余的任何东西
    • 在您的尺寸准备好之前它不会阻塞。它会让你得到尽可能多的东西(0 是可能的) - 我认为这种行为可以改变,但它在另一端没有任何字节数 Write()n
    • 您需要构建缓冲区
    • 是的,您确实需要手动构建缓冲区,方法是在数据前面加上它的长度

    这里,你对如何读取缓冲区有一些想法:.NET blocking socket read until X bytes are available?

    【讨论】:

    • @RamanZhylich 这是我 12 年前读过的关于 TCP/IP 的书 :)
    【解决方案2】:

    Windows 套接字没有内部同步机制。因此,您永远无法确定您获得的字节部分是最终的,并且不需要其他数据。您总是需要跟踪所有检索到的数据并决定何时可以停止检索。

    【讨论】:

      【解决方案3】:

      如果流耗尽,您将获得 0 的读取大小,或者至少为 1 直到您的缓冲区大小。它可以是该范围内的任何大小。常见大小是网络 MTU 的倍数(大约 1452 字节)。

      您需要自己实现逻辑以逐渐将缓冲区填充到所需大小。

      发送的块大小和接收的块大小之间没有联系。

      文件系统基本上是唯一常见的 Stream 实现,它总是完全填满请求的缓冲区,除了文件末尾。其他 Stream 实现不提供这种保证。

      所有这些都是为了性能而做出的设计选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 2011-02-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-01
        • 2020-12-17
        相关资源
        最近更新 更多