9

ポートで受信するスレッドを開始するとします。ソケット呼び出しは recvfrom でブロックされます。次に、どういうわけか別のスレッドで、ソケットを閉じます。

Windows では、これにより recvfrom のブロックが解除され、スレッドの実行が終了します。

Linux では、これは recvfrom のブロックを解除しません。その結果、私のスレッドは永遠に何もせずに座ったままになり、スレッドの実行は終了しません。

Linux で何が起こっているのか、誰か助けてもらえますか? ソケットが閉じられたら、recvfrom にブロックを解除してもらいたい

select() の使用について読み続けていますが、特定のケースでの使用方法がわかりません。

4

4 に答える 4

17

shutdown(sock, SHUT_RDWR)ソケットで呼び出し、スレッドが終了するのを待ちます。(つまりpthread_join)。

close()これでのブロックが解除されると思うかもしれrecvfrom()ませんが、Linux ではそうではありません。

于 2011-11-01T21:19:44.847 に答える
6

この問題に対処するために select() を使用する簡単な方法のスケッチを次に示します。

// Note: untested code, may contain typos or bugs
static volatile bool _threadGoAway = false;

void MyThread(void *)
{
   int fd = (your socket fd);
   while(1)
   {
      struct timeval timeout = {1, 0};  // make select() return once per second

      fd_set readSet;
      FD_ZERO(&readSet);
      FD_SET(fd, &readSet);

      if (select(fd+1, &readSet, NULL, NULL, &timeout) >= 0)
      {
         if (_threadGoAway)
         {
            printf("MyThread:  main thread wants me to scram, bye bye!\n");
            return;
         }
         else if (FD_ISSET(fd, &readSet))
         {
            char buf[1024];
            int numBytes = recvfrom(fd, buf, sizeof(buf), 0);
            [...handle the received bytes here...]
         }
      }
      else perror("select");
   }
}

// To be called by the main thread at shutdown time
void MakeTheReadThreadGoAway()
{
   _threadGoAway = true;
   (void) pthread_join(_thread, NULL);   // may block for up to one second
}

より洗練された方法は、select のタイムアウト機能の使用を避け、代わりに (socketpair() を使用して) ソケット ペアを作成し、I/O スレッドが必要なときにメイン スレッドがソケット ペアの最後にバイトを送信するようにすることです。ソケットペアの反対側のソケットでバイトを受信すると、I/O スレッドが終了します。ただし、それは読者の演習として残しておきます。:)

select() がソケットが読み取り可能であることを示した後でも、recvfrom() 呼び出しがブロックされる可能性がある (小さいがゼロではない) 可能性を回避するために、ソケットを非ブロック モードに設定することもしばしば良い考えです。 、ここで説明されているように。ただし、ブロッキングモードは目的には「十分」かもしれません。

于 2011-06-18T00:37:01.667 に答える
4

答えではありませんが、Linux の close man ページには興味深い引用が含まれています。

ファイル記述子が同じプロセス内の他のスレッドのシステム コールによって使用されている可能性があるときに、ファイル記述子を閉じることはおそらく賢明ではありません。ファイル記述子は再利用される可能性があるため、意図しない副作用を引き起こす可能性があるいくつかの不明瞭な競合状態があります。

于 2011-06-17T18:25:12.037 に答える