C/C++ 中的并发 UDP 连接限制
Posted
技术标签:
【中文标题】C/C++ 中的并发 UDP 连接限制【英文标题】:Concurrent UDP connection limit in C/C++ 【发布时间】:2015-10-28 15:18:47 【问题描述】:我写了一个server in c
,它从端口X
中的客户端接收UDP
数据。我使用Epoll(non block)
套接字进行UDP
监听,并且只有一个线程作为工作线程。伪代码如下:
on_data_receive(socket)
process(); //take 2-4 millisecond
send_response(socket);
但是当我发送5000 concurrent
(使用线程)请求服务器错过5-10%
请求。 on_data_receive() 从未要求 5-10% 的请求。我正在本地网络中进行测试,因此您可以假设没有丢包。我的问题是为什么 on_data_receive 没有要求一些请求?套接字的连接限制是多少?随着并发请求的增加,丢包率也随之增加。
注意:在将请求发送到服务器之前,我使用了长达 200 毫秒的随机睡眠。
【问题讨论】:
你永远不能假设 UDP 没有丢包,即使在本地网络上也是如此。cat /proc/sys/fs/file-max
的输出是什么? 5000 个线程和 5000 个连接可能会耗尽内存?
调用系统函数的第二个参数是什么:listen()
?通常(嵌入式Linux实际上对UDP数据包进行排队)如果接收者在下一个数据包到达之前还没有准备好读取UDP数据包,则第一个数据包会丢失/被下一个UDP数据包覆盖。代码实际上是否为每个数据包创建一个新连接?如果是这样,那将大大减少可用的吞吐量
请发布实际代码。现代计算机应该能够跟上数据包之间平均 100 毫秒的 UDP 连接
没有UDP连接这样的东西。
【参考方案1】:
UDP 没有“连接”。所有数据包都只是在对等方之间发送,操作系统会做一些神奇的缓冲来在一定程度上避免数据包丢失。
但是当太多数据包到达时,或者如果接收应用程序读取数据包的速度太慢,一些数据包会在没有通知的情况下被丢弃。这不是错误。
例如,Linux 有一个 UDP 接收缓冲区,默认情况下约为 128k(我认为)。或许你可以改变,但它不太可能解决 UDP 可能暴露丢包的系统性问题。
UDP 没有像 TCP 那样的拥塞控制。暴露了底层传输(以太网、本地网络)的原始工件。您的 5000 个发送者总共获得的 CPU 时间可能比您的接收者多,因此他们可以发送比接收者接收更多的数据包。当接收方无法继续接收数据包时,使用 UDP 发送方不会被阻止(例如在 sendto() 中)。使用 UDP,发送方总是需要明确控制和限制数据速率。没有来自网络侧的背压(*)。
(*)理论上UDP没有背压。但是在某些操作系统(例如 Linux)上,您可以观察到当通过本地以太网发送时存在背压(至少在某种程度上)。当物理网络接口的网络驱动程序报告它很忙(或者它的缓冲区已满)时,操作系统会在 sendto() 中阻塞。但是,当本地网络适配器无法确定整个网络路径的网络“忙”时,这种背压就会停止工作。另请参阅“以太网流量控制(暂停帧)”。通过这种方式,即使接收方的接收缓冲区已满,发送方也可以阻止发送应用程序。这就解释了为什么 UDP 背压似乎经常像 TCP 背压一样,尽管 UDP 协议中没有任何东西支持背压。
【讨论】:
以上是关于C/C++ 中的并发 UDP 连接限制的主要内容,如果未能解决你的问题,请参考以下文章