我正在使用 Linux 系统(带有 2.6.20 内核的 Ubuntu 7.04 服务器)。
我有一个程序,它有一个线程(thread1)等待选择一个 UDP 套接字变得可读。我正在使用 select(我的套接字作为单个 readfd 和单个 exceptfd),而不是只调用 recvfrom,因为我想要超时。
从另一个线程,我关闭并关闭了套接字。如果我在 thread1 在 recvfrom 中阻塞时执行此操作,则 recvfrom 将立即终止。如果我在线程 1 在超时的选择中阻塞时执行此操作,则选择不会立即终止,但最终会正确超时。
谁能告诉我为什么一旦套接字关闭,选择就不会退出?那不是例外吗?我可以看到它在哪里不可读(显然),但它已关闭,这似乎是例外。
这是套接字的打开(所有错误处理都被删除以保持简单):
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);
更新:显然(如下所述),关闭套接字不是例外情况(从选择的角度来看)。我想我需要知道的是:为什么?而且,这是故意的吗?
我真的很想了解这种选择行为背后的想法,因为它似乎与我的期望背道而驰。因此,我显然需要调整我对 TCP 堆栈如何工作的想法。请给我解释一下。