正在丢弃Winsock UDP数据包?

正在丢弃Winsock UDP数据包?,c,udp,winsock,network-protocols,C,Udp,Winsock,Network Protocols,我们在windows中通过UDP设置了客户机/服务器通信系统。我们面临的问题是,当吞吐量增加时,数据包会被丢弃。我们怀疑这是由于UDP接收缓冲区不断被轮询,导致缓冲区被阻塞并丢弃任何传入数据包。读取此缓冲区是否可能导致丢弃传入的数据包?如果是,有哪些选项可以纠正此问题?该系统是用C写的。请让我知道,如果这是太模糊,我可以尝试提供更多的信息。谢谢 对此不确定,但在windows上,无法轮询套接字并导致数据包丢失。Windows将从轮询中单独收集数据包,并且不会导致任何丢弃 我假设您使用select

我们在windows中通过UDP设置了客户机/服务器通信系统。我们面临的问题是,当吞吐量增加时,数据包会被丢弃。我们怀疑这是由于UDP接收缓冲区不断被轮询,导致缓冲区被阻塞并丢弃任何传入数据包。读取此缓冲区是否可能导致丢弃传入的数据包?如果是,有哪些选项可以纠正此问题?该系统是用C写的。请让我知道,如果这是太模糊,我可以尝试提供更多的信息。谢谢

对此不确定,但在windows上,无法轮询套接字并导致数据包丢失。Windows将从轮询中单独收集数据包,并且不会导致任何丢弃


我假设您使用select()轮询套接字?据我所知,它不会导致数据包丢失。

是的,堆栈被允许在缓冲区太满时以静默方式丢弃数据包。这是UDP特性的一部分,UDP是从TCP切换时放弃的可靠性之一。您可以通过添加重试逻辑、ACK数据包等来彻底改造TCP,也可以在这两者之间切换,比如


有很多方法可以增加堆栈的缓冲区大小,但这在很大程度上忽略了要点。如果您的读取速度不足以保持缓冲区空间可用,那么增大缓冲区只会推迟缓冲区空间耗尽所需的时间。正确的解决方案是在您自己的代码中创建更大的缓冲区,并尽快将数据从堆栈的缓冲区移动到程序的缓冲区中,在缓冲区中数据可以等待任意长的时间进行处理。

数据包可能会因路径上任何位置的不相关网络流量增加或接收缓冲区已满而丢失。为了缓解这种情况,可以增加Winsock中的接收缓冲区大小

从本质上讲,UDP是一种不可靠的协议,因为无法保证数据包的传递,并且在传递失败时不会向发送方返回错误。如果您担心数据包丢失,最好将确认数据包实现到您的通信协议中,或者将其移植到更可靠的协议(如TCP)中。实际上没有任何其他真正可靠的方法来防止UDP数据包丢失

读取此缓冲区是否可能导致丢弃传入的数据包

如果数据包到达的速度快于您读取数据包的速度,则数据包可能会被丢弃

如果是,有哪些选项可以纠正此问题

一个选项是更改网络协议:使用TCP,或者使用UDP实现一些确认+流控制

否则,你需要了解为什么你阅读速度不够快/不够频繁

如果CPU的利用率为100%,那么您需要减少每个数据包的工作量或获得更快的CPU(或者使用多线程和更多CPU,如果您还没有这样做的话)

如果CPU不是100%,那么可能发生的情况是:

  • 你读了一个包
  • 你做了一些工作,需要x毫秒的实时时间,其中一些被阻塞在其他I/O上(因此CPU不忙,但不用于读取另一个数据包)
  • 在这x毫秒期间,大量数据包到达,一些数据包被丢弃
解决这个问题的方法是改变线程

另一种可能是从套接字同时进行多次读取(每次读取都提供一个缓冲区,可以在其中接收UDP数据包)


另一种可能是查看是否有(O/s特定)配置选项来增加网络堆栈愿意缓冲的已接收UDP数据包的数量,直到您尝试读取它们。

Windows套接字中的默认套接字缓冲区大小为8k或8192字节。使用Windows函数增加缓冲区的大小(请参阅SO_RCVBUF选项)

但除此之外,如果读取数据包的速度不够快,增加接收缓冲区的大小只会延迟数据包再次被丢弃的时间

通常,这种情况下需要两个线程

第一个线程的存在只是为了服务套接字。换句话说,线程的唯一目的是从套接字读取数据包,将其添加到某种适当同步的共享数据结构中,发出已接收到数据包的信号,然后读取下一个数据包

存在第二个线程来处理接收到的数据包。它一直处于空闲状态,直到第一个线程发出接收到数据包的信号。然后,它从正确同步的共享数据结构中提取数据包并对其进行处理。然后等待再次发出信号


作为一种测试,尝试缩短对数据包的完整处理,并在每次收到数据包时向控制台(或文件)写入一条消息。如果您可以在不丢弃数据包的情况下成功地执行此操作,那么将功能分为“接收”线程和“处理”线程将有所帮助。

第一步,增加接收器缓冲区大小,Windows几乎会批准所有合理大小的请求

如果这没有帮助,那么您的消费代码似乎有一些相当缓慢的地方。我会使用线程,例如pthreads,并利用生产者-消费者模式将传入的数据报放入另一个线程的队列中,然后从那里消费,这样您的接收呼叫就不会阻塞,缓冲区也不会满

第三步,修改应用程序级协议,在发送方允许批处理数据包和批处理数据包,以减少发送大量小数据包时的UDP报头开销

第四步检查您的网络设备、交换机等。可以为您提供有关其流量统计信息、缓冲区溢出等的详细输出-如果存在问题,请使用更快的交换机或可能切换出故障的交换机

。。。仅供参考,我在后端连续运行UDP多播流量,平均速度约为30 Mbit/s,峰值为70 Mbit/s,我的丢包率为零。

hmm