この問題に対処するために 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() 呼び出しがブロックされる可能性がある (小さいがゼロではない) 可能性を回避するために、ソケットを非ブロック モードに設定することもしばしば良い考えです。 、ここで説明されているように。ただし、ブロッキングモードは目的には「十分」かもしれません。