3

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

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

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

4

3 回答 3

2

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

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

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

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

编辑:

要解决您的问题:

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

在这里,您对如何读取缓冲区有一些想法:.NET 阻塞套接字读取直到 X 字节可用?

于 2012-07-13T22:31:45.870 回答
0

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

于 2012-07-13T22:23:16.160 回答
0

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

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

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

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

这一切都是为了性能而做出的设计选择。

于 2012-07-13T22:26:31.453 回答