Unblock recvfrom when socket is closed

前端 未结 5 1279
自闭症患者
自闭症患者 2020-12-07 01:44

Let\'s say I start a thread to receive on a port. The socket call will block on recvfrom. Then, somehow in another thread, I close the socket.

On Windows, this will

5条回答
  •  长情又很酷
    2020-12-07 02:22

    Here's a sketch of a simple way to use select() to deal with this problem:

    // 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
    }
    

    A more elegant method would be to avoid using the timeout feature of select, and instead create a socket pair (using socketpair()) and have the main thread send a byte on its end of the socket pair when it wants the I/O thread to go away, and have the I/O thread exit when it receives a byte on its socket at the other end of the socketpair. I'll leave that as an exercise for the reader though. :)

    It's also often a good idea to set the socket to non-blocking mode also, to avoid the (small but non-zero) chance that the recvfrom() call might block even after select() indicated the socket is ready-to-read, as described here. But blocking mode might be "good enough" for your purpose.

提交回复
热议问题