处理UDP数据包流我写发送流UDP数据包到服务器的客户端程序。在服务器中,无论何时接收到UDP数据包,都应该进行一些处理并将数据包发送回客户端。在服务器
对于这种情况,我应该有实现服务器在队列处理UDP数据包或底层协议层处理此流?
换句话说,只要服务器接收到UDP数据包,进行处理并再次使用recvfrom()
API等待下一个UDP数据包,它就等于使用recvfrom()
API的UDP数据包就足够了。
处理UDP数据包流我写发送流UDP数据包到服务器的客户端程序。在服务器中,无论何时接收到UDP数据包,都应该进行一些处理并将数据包发送回客户端。在服务器
对于这种情况,我应该有实现服务器在队列处理UDP数据包或底层协议层处理此流?
换句话说,只要服务器接收到UDP数据包,进行处理并再次使用recvfrom()
API等待下一个UDP数据包,它就等于使用recvfrom()
API的UDP数据包就足够了。
我觉得你不需要处理UDP数据包到服务器端,底层网络协议(最协议的做到这一点,但你不依赖于它)做你的工作。
现在关于在服务器端等待UDP数据包,您可以使用非阻塞套接字连接,因此每次轮询该函数(或放在while(1)
环路),它接受客户端的请求,如果客户端则连接简单地从它接收数据包。因此,下次如果您调用该函数,则检查客户端是否已连接,如果是,则只需从该连接接收UDP数据。
让我解释一下如何在您的服务器端接收数据包:
假设功能acceptUDPPaket()
功能为您
int accept_sock[5];
int serversock;//listen on this server socket
void acceptUDPPaket(void)
{
struct sockaddr client;
int clientsize;
char i;
int sock;
clientsize = sizeof(struct sockaddr_in);
for(i=0;i<5;i++) // I have take maximum 5 client connection
{
if(accept_sock[i] == SYS_SOCKETNULL)
{
//your accept socket code
//ex:
sock=accept(serversock, &client, &clientsize);
if(sock != NULL)
{
accept_sock[i] =sock;
break;
}
}
}
for(i=0;i<5;i++)
{
if(accept_sock[i] != NULL)
{
receveFrom(&accept_sock[i]);//receive UDP packet from client and process on it
}
}
}
所以可能像上面这样的代码伪清楚你的困惑。
Linux的TCP/IP协议栈肯定有一个UDP数据包缓冲区,其大小可调的sysctl -w net.core.rmem_max=
...等
,以防止您的服务器上的UDP数据包的损失将是刚刚来增大最大尺寸的最快方式和长度到非常大的值,如果它是可以接受的你和服务器管理员。
recvfrom()
与阻塞套接字是完全确定。
UDP没有内置流量控制。这意味着除非服务器不能保证以比客户端发送数据报更快的速度处理数据报,否则您最终将拥有一个完整的接收缓冲区,网络堆栈将丢弃传入的数据包。这与设置更大的缓冲区大小无关(只会延迟问题,但不会解决问题)。
因此,如果您知道某些,在哪些数据包被发送的速度,说每秒50张左右,是值得您的服务器可以轻松应付(在最坏的情况下,并不在最佳情况!),你很好与一个简单的阻止recvfrom
。
否则,除非丢失大量数据包的是一个不是问题的问题,你需要实现流量控制的一些方法是类似于TCP在做什么。例如:客户端可以发送最多20个数据包,并为每个收到的应答数据包加上一个数据包,这是非常简单的算法。
另一个(表观的)的解决办法是卸载处理和发送的回答一些工作线程的,但像增加缓冲器大小,但是这仅将这个问题向后一点,它并没有解决它。另外,服务器设计要复杂得多。但是,如果客户端可以以几乎无限的速度发送数据(例如,10G上每秒发送12-14百万个数据包),那么如果工作线程无法处理该卷,它最终将会超出处理能力。
'你必须使用非阻塞套接字连接' - 为什么? –
这是我的错误编辑答案。如果OP要运行很多任务,那么他必须使用非阻塞套接字,因为显然不要在一个任务中等待(ex.udp任务)。感谢您的正确评价 –