8

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 スタックがどのように機能するかについての考えを調整する必要があることは明らかです。説明してください。

4

6 に答える 6

4

UDP はコネクションレス プロトコルです。接続がないため、切断されることはありません。そのため、消費者はプロデューサーが二度と送信しないことを知りません。

プロデューサーに「ストリームの終わり」メッセージを送信させ、それを受信するとコンシューマーを終了させることができます。

于 2009-01-19T18:25:18.437 に答える
4

たぶん、選択をウェイクアップするために何か他のものを使用する必要があります。たぶんパイプかそのようなものです。

于 2009-01-26T19:54:10.570 に答える
3

select() が EINTR を返す原因となるシグナル (USR2 など) をスレッドに送信できませんか? 次に、シグナルハンドラで、select()? を再起動しないように指示するフラグを設定します。

これにより、複数のファイル記述子を待機する必要がなくなり、パイプを使用してそれを強制終了するよりもずっときれいに見えます。

于 2009-07-27T10:15:06.920 に答える
2

最も明白な解決策は、閉鎖されていることを例外的な条件と見なさないことだと思います。問題の根本は、あなたが の哲学を実際に受け入れていないことにあると思いますselect。なぜ別のスレッドでソケットをいじっているのか、それは災害のレシピのように聞こえます。

于 2009-01-22T10:34:04.313 に答える
2

違いは、recvfrom が単一のソケットから積極的にメッセージを読み取ろうとしているということです。select はメッセージが到着するのを、おそらく複数のハンドルで待機しており、必ずしもソケット ハンドルであるとは限りません。

于 2009-01-26T19:46:37.433 に答える