在UNIX/LINUX下,非阻塞模式SOCKET可以采用recv+MSG_PEEK的方式进行判断,其中MSG_PEEK保证了仅仅进行状态判断,而不影响数据接收。
对于主动关闭的SOCKET, recv返回-1,而且errno被置为9(#define EBADF 9 /* Bad file number */)或104 (#define ECONNRESET 104 /* Connection reset by peer */)
对于被动关闭的SOCKET,recv返回0,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)
对正常的SOCKET, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)
因此对于简单的状态判断(不过多考虑异常情况),
recv返回>0, 正常
返回-1,而且errno被置为11 正常
其它情况 关闭
另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。
最后,如果recv的返回值为0,那表明对方已将连接断开,我们的接收操作也应该结束。
accetp()是慢系统调用,在信号产生时会中断其调用并将errno变量设置为EINTR,此时应重新调用accept()。
所以使用时应这样:
while(1) {
if ( (connfd = accept(....)) == -1 ) {
if (errno == EINTR)
continue;
perror("accept()");
exit(1);
}
/* do sth with "connfd" */