如accept()
部分的RETURN VALUE
手册页中所述:
错误处理
Linuxaccept()
(和accept4()
)将新套接字上已有的网络错误作为accept()
的错误代码传递。此行为与其他BSD套接字实现不同。为了可靠运行,应用程序应检测accept()
之后为协议定义的网络错误,并通过重试将其视为EAGAIN
。在TCP / IP的情况下,这些是ENETDOWN
,EPROTO
,ENOPROTOOPT
,EHOSTDOWN
,ENONET
,EHOSTUNREACH
,{{1} }和EOPNOTSUPP
。
这是否意味着必须在ENETUNREACH
返回之后和检查errno
的返回值之前检查accept()
的值?如果是,如果设置accept()
,必须采取哪些步骤?
这是我处理errno
的代码片段:
accept()
我的结论是,在这种情况下,人们可能会在一段时间内再试一次。我的结论是否正确?
答案 0 :(得分:3)
根据SUSv4:
成功完成后,
accept()
将返回已接受套接字的非负文件描述符。否则,将返回-1
并设置errno
以指示错误。
这意味着,如果errno
返回accept()
,您只需检查-1
。
您的代码可能看起来更像这样:
ret = accept(fd, &addr, sizeof (addr));
if (ret == -1) {
switch (errno) {
case EAGAIN:
case EWOULDBLOCK:
/* do something */
break;
case EBADF:
/* do something different */
break;
default:
/* do something even more different */
}
}
(您如何处理每个错误情况取决于您的应用程序。)
此外,在检查errno
的返回值后,务必立即检查accept()
。如果您先调用任何其他函数(即使是简单的fprintf()
),也可能会因错误而覆盖errno
。
答案 1 :(得分:2)
首先,检查accept()
返回值。如果accept()
返回值小于0
,则应检查errno
。如果是ENETDOWN
,EPROTO
,ENOPROTOOPT
,EHOSTDOWN
,ENONET
,EHOSTUNREACH
,EOPNOTSUPP
或{{1} },然后你可以再次致电ENETUNREACH
。否则发生了一些不好的事情,你应该停止拨打accept()
(你已经通过了不好的侦听套接字作为accept()
的参数,例如)。
这就是我对代码的理解。
以下是如何进行错误处理:
accept()
答案 2 :(得分:0)
您还应该处理EHOSTUNREACH
,该消息显示“软件导致连接中止”。
我像接受的答案一样处理了accept()
的返回值,但是我的一台服务器由于EHOSTUNREACH
而崩溃。
在google之后,我意识到ECONNABORTED
错误发生后套接字凭据也没有更改。我们不应该只为ECONNABORTED
而使程序崩溃。
其各种约束如下:
如果尚未建立连接,即这是来自客户端的第一个请求,并且即使在服务器没有机会响应之前客户端也关闭了连接,请在以下位置接受accept():服务器结果为ECONNABORTED
。服务器应忽略此错误,并继续处理队列中的下一个请求。如果客户端需要再次连接到服务器,则必须执行另一个connect()。
如果客户端与服务器之间的连接处于ESTABLISHED状态,并且客户端突然关闭连接,则服务器上的accept()调用将生成ECONNABORTED
。在这种情况下,服务器必须关闭半打开的连接。否则,只要服务器进程处于活动状态,那些半开的套接字就可以保持CLOSE_WAIT状态。请访问以下网页:http://technopark02.blogspot.com/200...closewait.html,以了解在稍有不同的情况下CLOSE_WAIT及其影响的更多信息。
最后,完整的代码如下:
while(running)
{
sfd = accept(socketFd, (struct sockaddr *) &cli_addr, &addr_len);
if( sfd < 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENONET ||
errno == EPROTO || errno == ENOPROTOOPT || errno == EOPNOTSUPP ||
errno == ENETDOWN || errno == ENETUNREACH || errno == EHOSTDOWN ||
errno == EHOSTUNREACH || errno == ECONNABORTED)
{
log_warn("accept error: %s\n", strerror(errno));
break;
}
else if( errno == EINTR)
{
continue;
}
else
{
log_error("AccepCb: accept error: %s\n", strerror(errno));
assert(false);
}
}
// logical works...
}