Вот эскиз простого способа использования 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 завершится, когда он получит байт в свой сокет на другом конце пары сокетов. Я оставлю это как упражнение для читателя. :)
Часто также неплохо установить сокет в неблокирующий режим, чтобы избежать (небольшой, но ненулевой) вероятности того, что вызов recvfrom () может заблокироваться даже после того, как select () указал, что сокет готов читать, как описано здесь . Но режим блокировки может быть «достаточно хорошим» для вашей цели.