Linuxシステム(2.6.20カーネルを搭載したUbuntu 7.04サーバー)で作業しています。
UDP ソケットが読み取り可能になるのを選択で待機しているスレッド (thread1) を持つプログラムがあります。タイムアウトが必要なため、recvfrom を呼び出すだけでなく、(ソケットを単一の readfd および単一の exceptfd として) select を使用しています。
別のスレッドから、ソケットをシャットダウンして閉じます。スレッド 1 が 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);
更新: 明らかに (以下で説明するように)、ソケットを閉じることは例外的な条件ではありません (select の観点から)。私が知る必要があるのは、なぜですか?そして、それは意図的ですか?
私の期待に反しているように見えるので、この選択動作の背後にある考え方を本当に理解したいと思っています。したがって、TCP スタックがどのように機能するかについての考えを調整する必要があることは明らかです。説明してください。