TCP Comm:在处理大数据包大小时,如何通知接收方有新数据?

TCP Comm: How is the receiver notified for new data when working with large data packet sizes?

假设在 2 个伙伴 A 和 B 之间建立了 TCP 连接。他们都使用 WinSocket(或其他 API)。现在调用 send() api 函数将长度设置为 100kByte 以发送他的应用程序数据。 我知道这 100kByte 可以被放入 TCP 协议级别的任意数量的消息中,并且 TCP 会注意所有这些块将以正确的顺序附加到接收方。我想弄清楚的是接收方多久会收到一次有新数据可用的通知。 WinSock 是否会等到收到完整的有效负载 (-> 100kB),然后设置相应的套接字并允许应用程序立即获取整个数据包,或者应用程序可能会一点一点地获取数据,因此必须这样做如果需要一次消耗 100kByte,内部缓冲本身?

我发送的消息看起来是这样的: 消息头 |有效载荷

因此我依赖于一次收到一条完整的消息。如果它是点点滴滴,它会搞乱我的消息处理。

我知道 TCP 是面向流的,而面向消息的协议 (UDP?) 可能更适合我的需要。但是我想知道我是否可以使用 TCP。

感谢您的帮助!

查看文档。 recv() 在阻塞模式下的约定是阻塞,直到至少传输了一个字节,或 EOS 或发生错误。在缓冲区被填满之前没有阻塞。

如果你想要消息,你必须自己实现它们。 TCP 是一种字节流协议。

您需要修正代码。调用 recv,将您收到的数据附加到上次调用的任何剩余数据上。如果您没有收到完整的消息,请再次致电 recv,直到收到为止。如果您确实有整条消息,请对其进行处理,为下一次传递保存所有剩余数据。

不要使用 UDP。如果您使用 UDP,您将需要自己实现所有 UDP 不能做的事情,例如重新排序、重新传输、慢启动、指数退避等。这比仅仅编写适当的接收逻辑来解析来自字节流的消息要多得多。

作为程序员,您始终可以检查接收数据的速度,这是我的 C# 示例,但我认为您会明白其中的要点:

var stopwatch = System.Diagnostics.Stopwatch.StartNew();

read = sr.Read(buffer, 0, packetSize); //attempt to read whole thing in one go
while (read < packetSize) //if it failed, read until you've read the whole thing
    read += sr.Read(buffer, read, packetSize- read); //read only as much as you need

stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds); //check how long it took

sr 是用于 read/write 操作的流对象。根据我的观察,即使我发送完全相同的数据包,读取值也不同,所以我猜这取决于 OS。尝试 TCP 或 UDP 连接,看看哪个更适合您。如果您经常发送大数据包,那么 UDP 会更好,因为它会产生更少的开销数据。