【发布时间】:2018-08-25 00:41:29
【问题描述】:
我的理解是 TCP 被认为是“可靠的”,因为接收方确认收到数据包并在有任何问题时请求重新发送。我的文件传输程序目前以 32767 字节的数据包发送文件,尽管我已经尝试过所有大小。发送需要 340 个数据包的 10 meg 文件始终会导致接收器上的三个或四个数据包明显小于发送的数据包。我总是得到一个与原始文件略有不同的文件。
例如,我的日志记录了所有收到的数据包的大小:
TCP packet received (32767 bytes)
TCP packet received (32767 bytes)
TCP packet received (14600 bytes)
TCP packet received (32767 bytes)
我的发送线程以 32767 字节块读取文件并调用发送子:
MyFile.Read(Buffer, 0, BufferSize)
SendTCPData(Address, Buffer)
我的 TCP 代码很简单:
Shared Sub SendTCPData(Address As String, ByVal Data As Byte())
Dim Client As New TcpClient(Address, PortNumber)
Dim Stream As NetworkStream = Client.GetStream()
Stream.Write(Data, 0, Data.Length)
Stream.Close()
Client.Close()
End Sub
有人可以帮忙吗? (“TCP 客户端到服务器通信”一文没有涉及如何处理接收到的数据包大小,这是我的问题。)
【问题讨论】:
-
你如何发送 32KB - 1byte...为什么是 32767?为什么不是像 32768 这样的偶数?即使在那里,您也应该考虑 IP 标头以适应这样的固定大小缓冲区。它不会阻止您遇到问题。您在上传期间从不校验您的文件?与其转储文件并假设 TCP 将无错误地控制流,不如向客户端发送 ACK 以发送下一个数据包。如果您不想为了速度而对每个数据包都进行处理,那么您应该对它们进行编号以便能够重新发送损坏的数据包。
-
TCP 是面向字节的。当你给 TCP 层一个 32767 字节的块时,它将把它分成多个段,在不同的数据包中发送。如何将接收到的数据写入文件?
-
32767 在我找到的示例代码中使用。它只是无符号 16 位值的最大大小,有点随意。我的(简化的)接收代码如下所示。每次收到数据包时都会调用它:
-
您的代码的问题在于它假定一个发送=一个接收,这是不正确的。 TCP 是一种流式协议,这意味着它在应用层没有数据包的概念。当您调用
Read()时,它会读取它下载的所有内容到目前为止,因此这可能小于实际数据的大小(这是您遇到的问题经历)。我的代码通过跟踪每个“数据包”包含多少数据来解决这个问题,并且在读取整个数据包之前它不会将数据传递给您。有关其工作原理的信息,请参阅:stackoverflow.com/a/37352525