マルチスレッドでソケットプログラミングを行う場合、
Accept 関数でスレッドがブロックされている場合、
メインスレッドはプロセスをシャットダウンしようとしています。
安全にpthread_joinするためにaccept関数を壊す方法は?
受け入れ機能を壊すために、それ自体を独自のポートに接続することでこれを行う方法について、漠然とした記憶があります。
どんな解決策も感謝します。
乾杯
いくつかの選択肢:
a) ノンブロッキングを使用する
b) AcceptEx() を使用して追加のシグナルを待機する (Windows)
c) 別のスレッドからリッスンしているソケットを閉じて、Accept() がエラー/例外を返すようにします。
d) 別のスレッドから一時的なローカル接続を開き、一時的な接続で Accept() を返すようにする
システムによっては、使用可能な場合は、select
関数を使用してサーバーソケットが読み取られるのを待ち、ソケットが接続しようとしていることを示します。接続を待機する時間は、クライアントが接続するのを待機するたびに設定/調整できます(無限、秒、0に設定すると、チェックして戻ります)。制限時間に達した(ソケットが接続を試みていない)かどうか、またはサービスを待機しているものがあるかどうか(接続したいクライアントがあることを示すサーバーソケット)を確認するために、リターンステータスをチェックする必要があります。accept
次に、返されたステータスに基づいて接続するソケットがあること を認識して実行できます。
これに対する典型的なアプローチは、受け入れるものがない限り使用しないことです! accept()
これを行う方法はpoll()
、ループ内で適切なタイムアウトを使用して、対応するソケットに接続することです。ループは、適切に同期されたフラグが設定されたために終了することを意図しているかどうかをチェックします。
別の方法は、ブロックされたスレッドにシグナルを送信することpthread_kill()
です。accept()
これは、適切なエラー表示でブロックから抜け出します。繰り返しますが、次のステップは、フラグをチェックして、スレッドが終了することを意図しているかどうかを確認することです。ただし、私の好みは最初のアプローチです。
利用可能な場合は、この機能を実現するために、ループでタイムアウトのある選択関数を使用します。
グレンが提案したように
タイムアウト値を指定した select 関数は、ソケットが一定時間接続するのを待ちます。ソケットが接続を試みた場合、その間は受け入れられます。この選択をタイムアウトでループすることにより、ブレーク条件が満たされるまで新しい接続をチェックすることができます。
次に例を示します。
std::atomic<bool> stopThread;
void theThread ( std::atomic<bool> & quit )
{
struct timeval tv;
int activity;
...
while(!quit)
{
// reset the time value for select timeout
tv.tv_sec = 0;
tv.tv_usec = 1000000;
...
//wait for an activity on one of the sockets
activity = select( max_sd + 1 , &readfds , NULL , NULL , &tv);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
...
}
}
int main(int argc, char** argv)
{
...
stopThread = false;
std::thread foo(theThread, std::ref(stopThread));
...
stopThread = true;
foo.join();
return 0;
}
「選択」のより完全な例http://www.binarytides.com
私は C++ にかなり慣れていないので、コードと回答を改善できると確信しています。
あなたが探しているのはこれのように聞こえます: リッスン/受け入れソケットに知られている特別なフラグ変数を設定し、メイン スレッドがリッスン/受け入れソケットへの接続を開くようにします。リスニング/受け入れソケット/スレッドは、いつシャットダウンするかを知るために、接続を受け入れるたびにフラグをチェックする必要があります。
通常、マルチスレッドネットワーキングを実行する場合は、接続が確立されると(または確立の準備が整うと)スレッドを生成します。オーバーヘッドを減らしたい場合は、スレッドプールを実装するのはそれほど難しくありません。