Linux套接字编程中接受后的错误号

Bar*_*uda 3 c sockets linux error-handling

accept()手册页RETURN VALUE部分所述:

错误处理
Linux accept()(和accept4())将新套接字上已经挂起的网络错误作为错误代码从accept(). 此行为不同于其他 BSD 套接字实现。为了可靠运行,应用程序应该检测为协议定义的网络错误,accept()EAGAIN通过重试来处理它们。在TCP / IP的情况下,这些都是 ENETDOWNEPROTOENOPROTOOPTEHOSTDOWNENONETEHOSTUNREACHEOPNOTSUPP,和ENETUNREACH

这是否意味着必须errnoaccept()返回之后和检查 的返回值之前检查 的值accept()?如果是,如果errno设置,必须采取哪些步骤?

这是我的代码处理片段accept()

newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if((errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN ||
    errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH))
    return;
if (newsockfd < 0)
{
    // error
}
else if(newsockfd > 0)
{
    // accepted a new connection
}
else
{
    // blah blah blah
}
Run Code Online (Sandbox Code Playgroud)

我得出的结论是,在这种情况下,您可以稍后再试一次。我的结论正确吗?

ale*_*der 5

首先,您检查accept()返回值。如果accept()返回值小于0,则应检查errno。如果是ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, 或ENETUNREACH,那么您可以accept()再次调用。否则发生了一些不好的事情,你应该停止调用accept()(例如,你已经将错误的 listen socket 作为accept()参数传递了)。

这就是我对代码的理解。

以下是错误处理的完成方式:

while (running) {
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
    {
        // error
        perror ("accept");
        if((errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN ||
            errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)) {
            continue;
         }
         exit (EXIT_FAILURE);
    }

    // accepted a new connection
    // blah blah blah
}
Run Code Online (Sandbox Code Playgroud)