UDP发送()到本地主机在Winsock下丢弃数据包

UDP send() to localhost under Winsock throwing away packets?

本文关键字:Winsock 数据包 主机 发送 UDP      更新时间:2023-10-16

场景相当简单…不允许使用" sendto() ",所以使用" send() "代替…

winsock2.2下,在一台运行Windows 7 Professional的全新i7机器上正常运行…

使用SOCK_DGRAM套接字,客户端和服务器控制台应用程序通过localhost (127.0.0.1)连接来测试事情…

必须使用固定大小的数据包…

客户端套接字使用connect(),服务器套接字使用bind()

客户端通过一系列BLOCKING send()呼叫发送N个数据包。服务器只使用ioctlsocket调用FIONREAD,在while循环中运行,以不断等待接收printf()字节数…

数据包丢失,除非我把SLEEP()相当多的时间… 我的意思是如果我不使用SLEEP(),则接收套接字上的字节数在运行之间会有所不同…

已经玩了改变缓冲区大小,情况没有太大变化,除了现在没有溢出,但问题与延迟保持不变…

我看过很多关于send()recv()之间问题的讨论,但在这种情况下,recv()甚至没有参与…

的想法吗?


(注:

由于我无法控制的原因,我正在编程的约束是必需的,所以没有WSA, .NET, MFC, STL, BOOST, QT或其他东西)


这不是一个缓冲区溢出的问题,有三个原因:

  1. 输入和输出缓冲区都设置并检查为远远大于所有正在发送的信息。
  2. 没有recv(),只有通过ioctl()调用检查传入缓冲区,recv()在用户输入后很长时间被调用。
  3. send() -s之间添加>40msSleep()时,整个工作正常,即如果存在溢出,则没有数量的Sleep()会有帮助(again, see point (2))

包会丢失,除非我用相当数量的SLEEP()时间……我指的是接收套接字上的字节数如果我不使用SLEEP()…

这是预期的行为;正如其他人在评论中所说,UDP数据包可以并且确实因为任何原因而被丢弃。然而,在仅本地主机通信的上下文中,原因通常是某个地方的固定大小的数据包缓冲区已满,无法容纳传入的UDP数据包。请注意,UDP没有流量控制的概念,所以如果你的接收程序不能跟上你的发送程序,一旦缓冲区满了,丢包肯定会发生。

至于如何处理它,insert-a-call-to-sleep()解决方案并不是特别好,因为您没有很好的方法知道"正确的"睡眠持续时间应该是多少。(缩短一个sleep(),你仍然会丢失数据包;sleep()太长会导致数据传输速度变慢;当然,"最佳"值可能会因计算机而异,或以不明显的方式从一个时刻到下一个时刻而异)。

您可以做的一件事是切换到不同的传输协议,如TCP,或者(因为您只在本地主机内通信),一个简单的管道或套接字对。这些协议具有您正在寻找的无损FIFO语义,因此它们可能是这项工作的正确工具。

假设你需要使用UDP,然而,UDP数据包丢失对你来说将是一个不可避免的事实,但是你可以做一些事情来减少数据包丢失:

  1. send()在阻塞模式下,或者如果使用非阻塞的send(),一定要等到UDP套接字select()在调用send()之前为ready-for-write。(我知道你说你发送()在阻塞模式;我只是为了完整而包括这个)
  2. 让你的SO_RCVBUF设置在接收UDP套接字上尽可能大。缓冲区越大,它填满容量的可能性就越低。
  3. 在接收程序中,确保调用recv()的线程不做任何其他会阻止它返回下一个recv()调用的事情。特别是,没有阻塞操作(即使printf()也是一个阻塞操作,它会减慢线程的速度,特别是在Windows下,DOS提示符因加载时滚动缓慢而臭名昭著)
  4. 在一个单独的线程中运行接收器的网络recv()循环,除了调用recv()并将接收到的数据放入FIFO队列(或其他共享数据结构)之外什么都不做。然后,另一个线程可以在FIFO中执行检查和解析数据的时间要求较低的工作,而不必担心导致丢包。
  5. 以你能说服操作系统允许你运行的最高优先级运行UDP-receive线程。可以占用UDP-receive线程的其他任务越少,在这些延迟期间数据包被丢弃的机会就越少。

请记住,无论您如何聪明地减少UDP数据包丢失的机会,UDP数据包丢失仍然会发生。因此,无论如何,您需要提出一种设计,使您的程序即使在数据包丢失时仍能以合理有用的方式运行。这可以通过实现某种自动重发机制来实现,或者(取决于您想要实现什么)通过设计可以简单地忽略数据包丢失的协议来实现。