Stopping a receiver thread that blocks recv ()

I have a chat application that has a separate thread for listening to incoming messages.

while (main thread not calling for receiver to quit) { string message = tcpCon.tcpReceive(); // Relies on the recv() function processIncomingMessage(message); } 

This way of working has one big problem. Most of the time, the loop will block on recv() so that the receiver stream does not stop. What would be the right way to solve this problem without forcibly terminating the thread in a couple of seconds?

+6
source share
4 answers

Close the socket using shutdown() to close it to all receivers.

This outputs "recv return 0" to my system, indicating that the receiver saw an ordered shutdown. Comment on shutdown() and watch it hang forever.

For a longer period, the OP should fix the design using select or including an explicit message about the output to the protocol.

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <pthread.h> /* Free on my system. YMMV */ int port = 7777; int cd; void *f(void *arg) { /* Hack: proper code would synchronize here */ sleep(1); /* This works: */ shutdown(cd, SHUT_RDWR); close(cd); return 0; } int main(void) { /* Create a fake server which sends nothing */ int sd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in sa = { 0 }; const int on = 1; char buf; pthread_t thread; sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(port); setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); /* Other error reporting omitted for clarity */ if (bind(sd, (const struct sockaddr*)&sa, sizeof sa) < 0) { perror("bind"); return EXIT_FAILURE; } /* Create a client */ listen(sd, 1); cd = socket(AF_INET, SOCK_STREAM, 0); connect(cd, (const struct sockaddr*)&sa, sizeof sa); accept(sd, 0, 0); /* Try to close socket on another thread */ pthread_create(&thread, 0, f, 0); printf("recv returned %d\n", recv(cd, &buf, 1, 0)); pthread_join(thread, 0); return 0; } 
+10
source

You can use select () to wait for incoming data and avoid blocking in recv (). select () also blocks, but you can disable it after a specified interval so that the while loop can continue and verify that the signals stop from the main thread:

 while (main thread not calling for receiver to quit) { if (tcpCon.hasData(500)) { // Relies on select() to determine that data is // available; times out after 500 milliseconds string message = tcpCon.tcpReceive(); // Relies on the recv() function processIncomingMessage(message); } } 
+4
source

If you close the socket in another thread, then recv () will exit.

+2
source

calling close on a socket from any other thread will immediately exit recv .

+2
source

Source: https://habr.com/ru/post/901016/


All Articles