.net 写入TcpClient和NetworkStream

.net 写入TcpClient和NetworkStream,.net,tcpclient,.net,Tcpclient,对于如何在.net中使用tcp流,我有点困惑。 现在,当我想写的时候,比如说40字节,我把它写到一个memorystream,然后调用ToArray(),把memorystream写到networkstream+flush 在服务器端,我使用Read(buf,0,len)并检查长度是否与我期望的完全一致。我这样做是不是很愚蠢?我可以写尽可能少的字节,当我准备好阅读时就刷新吗 当我阅读()时,我总能得到我期望的长度吗?(假设应用程序是正确的,没有发生错误)它会阻止,直到我的尺寸准备好吗?我不需要循

对于如何在.net中使用tcp流,我有点困惑。 现在,当我想写的时候,比如说40字节,我把它写到一个memorystream,然后调用ToArray(),把memorystream写到networkstream+flush

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


当我阅读()时,我总能得到我期望的长度吗?(假设应用程序是正确的,没有发生错误)它会阻止,直到我的尺寸准备好吗?我不需要循环读取并构建缓冲区,是吗?假设我期望一个像10k或更大的大小,那么我需要构建我的缓冲区吗

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

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

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

发送的块大小和接收的块大小之间没有连接

文件系统基本上是唯一的通用流实现,它总是完全填满请求的缓冲区,除了在文件末尾。其他流实现不能保证这一点


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

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

TCP很容易被形象化为一根水管,一端装满一杯水。添加新的一杯水不会告诉你它的大小,只会向管道中添加更多的水

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

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

编辑:

要查看您的问题:

  • Flush()
    与此无关
  • 你不会得到你想要的尺寸。你将得到0到运输中剩余的任何东西
  • 在你的尺码准备好之前,它不会阻塞。它将尽可能多地为您提供信息(0是可能的)-我认为这种行为可以改变,但它的另一端不再有任何字节数
    Write()
    n
  • 您需要构建缓冲区
  • 是的,您确实需要手动构建缓冲区,在数据前面加上长度前缀

在这里,您对如何读取缓冲区有一些想法:

@RamanZhylich这是我12年前在TCP/IP上读到的一本书:)