调用recvmsg后跟epoll_wait()后udp套接字缓冲区变满

时间:2013-07-31 20:53:04

标签: c sockets unix udp

我遇到了UDP服务器套接字缓冲区被填满的问题。一旦缓冲区已满,数据包就会被丢弃。使用“netstat -anp | grep udp”监视套接字缓冲区大小。 UDP服务器调用epoll_wait(),然后调用recv_msg()。这是一个非阻塞的插座。

代码段如下 -

struct epoll_event ev = {(unsigned int)0};
ev.events = (unsigned int) (EPOLLIN | EPOLLET);
ev.data.fd = iSockFd;
int m_sdEpoll = epoll_create(1);

if(epoll_ctl(m_sdEpoll, EPOLL_CTL_ADD, iSockFd, &ev)<0)
{
    cout << "Epoll insertion error for sd  : " << iSockFd << endl;;
}

while( 1 )
{
    struct epoll_event events[1];
    int noEvt = epoll_wait(m_sdEpoll, events, 1 , -1);
    if(noEvt<0)
    {
        cout << "epoll_wait error no : "<< endl;
        continue;
    }
    for(int i=0; i<noEvt; i++)
    {
        int sd = events[i].data.fd; 

        int recv_bytes = recvmsg(sd, &msg, 0);

    } // end of for loop
}

问题是固定的(即套接字缓冲区不会填满)如果在循环中调用recvmsg直到找到EAGAIN,然后再去下一个描述符。

当从epoll_wait()收到的每个事件中只读取单个消息时,知道为什么套接字缓冲区会被填满

1 个答案:

答案 0 :(得分:1)

我现在已经很晚了,但我会尽力让自己明白:)

我将参考Epoll的手册页,例如可以在linux.die.net上找到。 当与EPOLLET一起使用时,epoll是边缘触发的(EPOLLET中的ET)。这意味着它将触发状态的变化。如果你收到多条消息,但只是在调用带有无限超时的epoll_wait()之前只读取了第一条消息,那么你自己就像手册页描述的那样基本上是死锁的。

总结一下:由于epoll_wait正在等待更改(从无消息到某些消息)但已有消息可用,因此状态转换以及事件永远不会发生。

编辑:偶然发现this回答类似问题。