我正在Linux系统(带有2.6.20内核的Ubuntu 7.04服务器)上工作。

我有一个程序,该程序有一个线程(thread1)等待选择使UDP套接字变得可读。
我使用的是select(将套接字作为单个readfd和单个exceptfd),而不是仅调用recvfrom,因为我想超时。

从另一个线程,我关闭并关闭套接字。
如果我在recvfrom中阻塞thread1时执行此操作,则recvfrom将立即终止。
如果我在线程1被超时选择阻塞时执行此操作,则该选择不会立即终止,但最终将正确超时。

谁能告诉我为什么关闭套接字后选择就不退出吗?这不是一个异常(exception)吗?我可以看到(显然)它不可读的地方,但是它是封闭的,这似乎很正常。

这是套接字的开口(为了简化起见,删除了所有错误处理):

m_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
struct sockaddr_in si_me;
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(m_sockfd, (struct sockaddr *)(&si_me), sizeof(si_me)) < 0)
{
// deal with error
}

这是thread1执行的select语句:
struct timeval to;
to.tv_sec = timeout_ms/1000;// just the seconds portion
to.tv_usec = (timeout_ms%1000)*1000;// just the milliseconds
                                    // converted to microseconds

// watch our one fd for readability or
// exceptions.
fd_set  readfds, exceptfds;
FD_ZERO(&readfds);
FD_SET(m_sockfd, &readfds);
FD_ZERO(&exceptfds);
FD_SET(m_sockfd, &exceptfds);

int nsel = select(m_sockfd+1, &readfds, NULL, &exceptfds, &to);

更新:显然(如下所述),关闭套接字并不是一种异常(exception)情况(从select的角度来看)。我想我需要知道的是:为什么?而且,这是故意的吗?

我真的很想了解这种选择行为背后的想法,因为这似乎与我的期望背道而驰。因此,我显然需要调整对TCP堆栈工作方式的看法。请给我解释一下。

最佳答案

也许您应该使用其他方法来唤醒选择。也许是 pipe 之类的东西。

10-07 12:35
查看更多