我的印象是UDP的不稳定性是物理层的属性,但似乎不是:
我试图通过UDP发送消息,UDP分为一系列数据包.消息识别和重新排序是隐式完成的.
我在同一台计算机上运行的两个应用程序上测试了这种方法,并期望它能够顺利运行.然而,即使数据传输在同一台机器上的两个程序之间,也存在数据包丢失,并且也非常频繁.损失似乎也是随机的:有时候整个信息都会通过,有时则不然.
现在,甚至在同一台机器上发生损失的事实让我想知道我做得对吗?
最初,我在一次拍摄中异步发送了消息的所有peices,而不是在发送下一个之前等待完成一个peice.
然后,我尝试从前一个完成例程中发送下一条消息.这确实提高了数据包丢失率,但并没有完全阻止它.
如果我在peices之间添加一个暂停(Sleep(...)),它可以100%工作.
编辑: 正如答案所建议的那样:数据包发送速度太快,操作系统的缓冲最小化.这是合乎逻辑的.
所以,如果我想阻止在系统中添加确认和重新传输(那时我可以使用TCP),我该怎么办?在不将数据速率降低到可能更高的水平的情况下,提高数据包丢失率的最佳方法是什么?
编辑2: 我发现问题可能不是完全缓冲区溢出,而不是缓冲区可用性.我正在使用异步WSARecvFrom来接收,根据我的理解,它会占用一个缓冲区来覆盖默认的OS缓冲区.当接收到数据报时,它被送入缓冲区,并且在缓冲区已满或不满时调用完成例程.
此时,根本没有缓冲区来处理传入的数据,直到从完成例程中重新调用WSARecvFrom.
问题是,是否有办法创建某种缓冲池,因此可以在处理不同的缓冲区时缓冲数据?
在您的情况下,您只是过快地发送数据包,以便接收进程读取它们.O/S只会在开始丢弃之前缓冲一定数量的接收数据包.
避免这种情况的最简单的机制是让接收进程发送回最小的ACK数据包,但是无论是否在几毫秒内没有收到ACK,发送进程都要继续进行.
编辑 - 基本上,UDP是"火与难忘".协议中没有内置的反馈机制,就像TCP一样.调整传输速率的唯一方法是远端告诉您它没有接收整个流.另请参阅RFC 2309.
Re:数据包序列 - 由于物理层不会发生重新排序,通常是因为IP网络是"分组交换"而不是"电路交换".
这意味着每个数据包可能通过网络采用不同的路由,并且由于这些不同的路由可能具有不同的延迟,因此数据包可能无序到达.
在实践中,由于物理层错误,目前很少有数据包丢失.数据包丢失是因为它们以高于管道可容纳的速率被送入有限吞吐量管道.缓冲可以通过平滑数据包流速来帮助解决这个问题,但是如果缓冲区填满,你就会回到正方形.