我还没有找到演示这个的示例代码。下面是我在一组套接字上测试的代码的一部分。注意(不在下面的代码中),我将“except_set”设置为“read_set”和“write_set”的并集,以便监视所有涉及的套接字。
基本上,我希望看到的是当错误发生时,它应该打印出一些套接字的错误列表。然而,我观察到的是“n==-1”的情况,它只给出一条错误消息(在我的情况下,“错误的文件描述符”)。最好打印出遇到错误的套接字。
另一个问题:由于只有一个“errno”,它如何表示多个套接字的错误(如果多个套接字在一个select()调用中遇到错误)。我真的很困惑。“except_set”会在每个套接字的基础上捕获哪种错误?正确的使用方法是什么?谢谢。
int n = select(max_fd + 1, &(read_set), &(write_set), &(except_set), &tv);
if (n == -1)
{
perror("select()");
exit(1);
}
else if (n == 0)
{
// process time-out ...
}
else // (n > 0)
{
for (int i=0; i < max_fd; ++i)
{
if (FD_ISSET(i, &(read_set)))
{
// process read
}
if (FD_ISSET(i, &(write_set)))
{
// process write
}
if (FD_ISSET(i, &(except_set)))
{
printf("error, %s, socket= %d", strerror(errno), i);
}
}
}
最佳答案
您要检查的值errno
与具有异常条件的套接字无关。事实上,这与select
无关。它只是以前某个调用的剩余部分,或者在非错误条件下被错误设置。只有在从标准库函数接收到故障返回值(通常是errno
或-1
)之后,NULL
才有意义。
至于特殊情况意味着什么:
如果套接字存在挂起错误,则应将其视为具有挂起的异常条件。否则,构成异常条件的是特定于文件类型的。对于与套接字一起使用的文件描述符,它是特定于协议的,如下所述除外。对于其他文件类型,它是实现定义的。如果该操作对于特定文件类型没有意义,pselect()或select()应指示描述符已准备好进行读或写操作,并应指示描述符没有挂起的异常条件。
...
如果在打开文件描述中清除了O_NONBLOCK且设置了MSG_OOB标志的接收操作将在不阻塞的情况下返回带外数据,则套接字应被视为有异常情况等待处理。(是否使用MSG_OOB标志来读取带外数据是特定于协议的。)如果接收队列中存在带外数据标记,则套接字也应被视为具有等待的异常情况。在其他情况下,套接字可能被认为有一个异常条件等待处理,具体协议和实现定义。
来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html
如果套接字具有错误状态,则可以使用SO_ERROR
的getsockopt
选项获取它。
通常,不需要将异常集与select
一起使用。如果套接字已经关闭,它将显示为可读的,并给您文件结尾(零长度读取)。然而,通常情况下,协议栈不会立即检测到连接丢失,因此您将只会收到一个试图写入套接字的写入错误(可能会SIGPIPE
,除非您禁止该错误),此时系统确定它无法再写入。就我个人而言,我从来没有机会在select
中使用特殊的集合。