C/C++中的并发UDP连接限制

sha*_*anu 1 c c++ sockets udp

我写了一个从端口的客户端server in c接收UDP数据X.我已经使用Epoll(non block)socket进行UDP监听,并且只有一个线程作为worker.伪代码如下:

on_data_receive(socket){
    process(); //take 2-4 millisecond
    send_response(socket);
} 
Run Code Online (Sandbox Code Playgroud)

但是当我发送5000 concurrent(使用线程)请求服务器未命中5-10%请求时.on_data_receive()从未调用过5-10%的请求.我正在本地网络测试,所以你可以假设没有丢包.我的问题是为什么on_data_receive没有要求一些请求?套接字的连接限制是多少?随着并发请求丢失率的增加也增加.

注意:在将请求发送到服务器之前,我使用了200毫秒的随机休眠.

Joh*_*ann 6

UDP没有"连接".所有数据包都只是在对等体之间发送,操作系统会进行一些魔术缓冲,以避免数据包在某种程度上丢失.

但是当太多数据包到达,或者接收应用程序读取数据包太慢时,某些数据包会在没有通知的情况下丢失.这不是错误.

例如,Linux有一个UDP接收缓冲区,默认情况下约为128k(我认为).您可以改变这种情况,但它不太可能解决UDP可能导致数据包丢失的系统问题.

使用UDP,没有像TCP那样的拥塞控制.底层传输的原始工件(以太网,本地网络)被暴露.你的5000个发送者总共可以获得比你的接收器更多的CPU时间,因此他们可以发送比接收器更多的数据包.使用UDP发送器时,如果接收器无法跟上接收数据包,则不会被阻止(例如,在sendto()中).使用UDP,发送方始终需要明确地控制和限制数据速率.网络侧没有背压(*).

(*)从理论上讲,UDP中没有背压.但在某些操作系统(例如Linux)的,你可以观察到存在背压(至少在一定程度上)在本地以太网比如发送时.当物理网络接口的网络驱动程序报告它正忙(或其缓冲区已满)时,OS会阻塞sendto().但是当本地网络适配器无法确定整个网络路径的网络"忙"时,此背压会停止工作.另请参见"以太网流量控制(暂停帧)".通过这种方式,即使接收侧的接收缓冲器已满,发送方也可以阻止发送应用.这就解释了为什么通常会出现类似TCP背压的UDP背压,尽管UDP协议中没有任何东西可以支持背压.