我们有超过UDP建立在Windows客户端/服务器通信系统。 我们所面临的问题是,当吞吐量的增长,数据包被越来越下降。 我们怀疑,这是由于其不断轮询造成堵塞缓冲区,并丢弃任何传入数据包的UDP接收缓冲区。 难道阅读本缓冲区会导致进入的数据包被丢弃? 如果是这样,有什么纠正这种选择? 该系统在C.书面请让我知道这是太含糊,我可以尝试提供更多的信息。 谢谢!
Answer 1:
在Windows套接字的缺省套接字缓冲区大小为8K或8192字节。 使用setsockopt的视窗功能,以增加缓冲的大小(指SO_RCVBUF选项)。
但除此之外,增加你的接收缓冲区的大小,只会延误,直到数据包得到再度回落,如果你不读包足够快的时间。
通常情况下,你希望两个线程这种情况。
第一个线程只存在于服务插座。 换句话说,线程的唯一目的是从套接字读数据包时,把它添加到某种适当同步的共享数据结构的,发信号通知数据包已经收到,然后读取下一个数据包。
第二个线程的存在是为了处理接收到的数据包。 它位于空闲状态,直到第一个线程信号的包已收到。 然后,它从正确同步共享数据结构拉动分组并处理它。 然后,等待再次被通知。
作为测试,尝试短路你的数据包的全部处理,只是每写一个数据包已经收到时间的消息到控制台(或文件)。 如果你能成功地做到这一点没有丢弃数据包,然后打破你的功能集成到一个“接收”线程和“处理”线程会有所帮助。
Answer 2:
是的,栈允许丢弃数据包 - 默默的,甚至 - 当其缓冲区过满。 这是UDP,可靠性位中的一个,你放弃当你从TCP切换自然的一部分。 您可以重塑TCP -很差-通过添加重试逻辑,ACK数据包,而这样,也可以切换到东西,像之间的SCTP 。
有办法增加堆栈的缓冲区大小,但是这主要是缺少了这一点。 如果你是不读的速度不够快,保持缓冲空间已经可用,使得缓冲区较大,只是要放一放,它把你用完缓冲空间的时间。 正确的解决办法是你自己的代码中做出更大的缓冲区,并从移动堆栈的缓冲区数据到你的程序的缓冲区尽快,它可以等待任意长的时间进行处理。
Answer 3:
难道阅读本缓冲区会导致进入的数据包被丢弃?
数据包可以比你读他们,如果他们更快地到达被丢弃。
如果是这样,有什么纠正这种选择?
一种选择是改变网络协议:使用TCP,或实现使用UDP一些确认+“流量控制”。
否则,你需要看到,为什么你不读快/往往不够。
如果CPU是100%utilitized那么你需要做的每个数据包较少的工作或获得更快的CPU(或者使用多线程和多CPU的,如果你是不是已经)。
如果CPU不是100%的话,或许发生的事情是:
- 你读一个包
- 你做了一些工作,这需要x的实时毫秒,其中有一些是花在阻止一些其他I / O(所以CPU不忙,但它没有被用来读取另一个数据包)
- 在这些X毫秒,数据包的洪水到达,一些被丢弃
针对此的解决方法是改变线程。
另一种可能性是做几个同时从插座中读取(您的每一个读出提供可接收的UDP包到其中的缓冲液)。
另一种可能性是,看看是否有一个(O / S专用)配置选项,以增加接收到的UDP数据包的数量,其网络堆栈愿意缓冲区,直到您尝试阅读。
Answer 4:
第一步,增加接收缓冲区的大小时,Windows几乎所有的赠款合理的规模要求。
如果没有帮助,你消耗的代码似乎有一些相当缓慢的地区。 我会用线程,例如使用并行线程和利用生产者消费者模式把传入的数据报在另一个线程队列,然后从那里消费,所以你接听电话不要阻挡和缓冲不会运行完整
第三步骤中,修改应用程序级协议,允许成批数据包和数据包批次在发送方从发送大量小数据包的减少UDP报头开销。
第四步检查您的网络设备,交换机等可以给你他们的流量统计详细的输出,缓冲区溢出等 - 如果这是在问题得到更快的开关或可能切换出一个错误的一个
...只是通知你,我对我们的后台持续运行的UDP多播流量的魅力。 〜处具有峰的70Mbit / s和我的下降速率30Mbit / sec是裸零
Answer 5:
不知道这一点,但在Windows,它无法轮询套接字,并导致数据包丢弃。 Windows Embedded从您的投票分别收集的数据包,它应该不会造成任何下降。
我假设你使用select()来轮询套接字? 据我所知,不能导致脱落。
Answer 6:
该数据包可能会丢失,由于沿线的任何地方增加了不相关的网络流量,或者完全接收缓冲区。 为了缓解这个问题,可以增加的Winsock接收缓冲区大小。
从本质上讲,UDP是在这个意义上不可靠的协议,该协议数据包传送不能保证,则返回到上递送失败发送者没有错误。 如果你担心丢包,这将是最好实现的确认数据包进入你的通信协议,或将其移植到像TCP更可靠的协议。 确实没有其他任何真正可靠的方法,以防止UDP数据包丢失。