阻塞套接字接受时出现EAGAIN错误

3

我正在使用阻塞式套接字来接受连接。我很少遇到这种错误,这使得调试变得困难。accept函数返回EAGAIN错误。那么对于一个阻塞式套接字来说,这怎么可能呢?

1个回答

2
如果套接字设置了接收超时(使用SO_RCVTIMEO套接字选项),那么当超时时间到达时,accept将返回EAGAIN
以下代码可演示此效果(还可以让您研究传递信号的影响):
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

#define TESTEXIT(s, f) if (s < 0) { perror(f); exit(1); }

void handler(int x)
{
    return;
}

int main()
{
    int s;
    int r;
    struct sockaddr_in sin;
    socklen_t sin_len = sizeof sin;
    struct timeval timeo = { .tv_sec = 5, .tv_usec = 0 };

    signal(SIGUSR1, handler);

    s = socket(PF_INET, SOCK_STREAM, 0);
    TESTEXIT(s, "socket");

    r = listen(s, 10);
    TESTEXIT(r, "listen");

    r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof timeo);
    TESTEXIT(r, "setsockopt");

    r = accept(s, (struct sockaddr *)&sin, &sin_len);
    TESTEXIT(r, "accept");

    return 0;
}

我认为内核代码中相关的部分可以在net/ipv4/inet_connection_sock.c中找到,在函数inet_csk_wait_for_connect()中。 对于我来说,不是完全清楚那里可能发生什么,但看起来该函数如果等待被除信号以外的任何其他东西打断,则会返回-EAGAIN(而信号确实会返回-EINTR)。 除了您提到的接收超时之外,我不知道还有哪些其他唤醒原因。 - Kristof Provost
@caf 我有一个带有recv超时的套接字,每个超时周期都会出现EAGAIN错误,我是否不应该在accept中使用超时,或者只是捕获错误并忽略它是否安全? - razz
@razzak: 超时的意义在于,它会导致阻塞调用在超时后返回,使您的程序能够及时响应并进行其他工作。因此,要么当 EAGAIN 返回时让您的程序响应超时,要么如果没有任何任务需要在超时时完成,就不要设置超时。 - caf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接