socket :: accept continuous返回EGAIN

时间:2016-09-02 06:12:30

标签: linux sockets

我使用非阻塞套接字来接收新连接。但是代码反复失败了accept()

int sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
::bind(sockfd, bind_addr, static_cast<socklen_t>(sizeof(struct sockaddr_in6)));
ret = ::listen(sockfd, SOMAXCONN);

while (True) {
    ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
    struct sockaddr_in6 addr;
    bzero(&addr, sizeof addr);
    socklen_t addrlen = static_cast<socklen_t>(sizeof *addr);
    int connfd = ::accept4(sockfd, sockaddr_cast(addr),
                         &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
}

errnoEAGAIN

2 个答案:

答案 0 :(得分:2)

从联机帮助页到accept(2)

  

EAGAIN或EWOULDBLOCK

     

套接字标记为非阻塞,并且不存在要接受的连接。 POSIX.1-2001允许在这种情况下返回错误,并且不要求这些常量具有相同的值,因此便携式应用程序应检查这两种可能性。

这意味着在客户端连接之前调用accept

答案 1 :(得分:1)

在致电accept之前,您必须致电listenbind但是由于您的套接字没有阻塞,您应该等待客户端等待连接。您可以使用select函数执行此操作:

int sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);

// addr is for accept call, sin for bind call
struct sockaddr_in6 addr, sin;
bzero(&addr, sizeof addr);

// prepare sin to tell bind to listen on any connection on given port
sin.sin6_family = family;
sin.sin6_addr = in6addr_any;
sin.sin6_port = htons(port); // choose port on which client could connect
sin.sin6_scope_id = 0;

// bind socket to interface
if (::bind(sock, (struct sockaddr*) &sin, sizeof(sin)) < 0)
{
    perror("bind");
}

// listen for new connection
if (::listen(sock, SOMAXCONN) < 0)
{
    perror("socket");
}

while (1)
{
    fd_set conset;
    FD_ZERO(&conset); 
    FD_SET(sockfd, &conset);

    struct timeval timeout = {10, 0};
    int maxfd = sockfd;

    // wait for new client
    select(maxfd + 1, &conset, NULL, NULL, &timeout);

    if (FD_ISSET(sockfd, &conset))
    {
        // a new client is waiting
        int connfd = ::accept(sockfd, &addr);
        if (connfd < 0)
        {
            perror("accept");
        }
        else
        {
            // do thing with new client
        }
    }
    else
    {
        printf("no new client in last 10 seconds")
    }
}