Bloquer le socket avec l’aide de Unix et C / C ++

J’essaie de comprendre ce qui bloque mon programme. J’exécute un serveur qui utilise des threads POSIX. Je dois pour mon laboratoire de programmation informatique. La fonction principale écoute les nouvelles connexions. Une fois qu’il accepte une connexion, il crée un nouveau thread en passant le FD au thread. Je parviens à me connecter au serveur à l’aide de plusieurs connexions telnet / client. Je peux envoyer des données au serveur avec succès une fois, mais si j’essaye d’envoyer à nouveau, le serveur ne fera rien.

Une partie de la fonction principale

int active_thread = 0; //The Running loop while(running) { if(active_thread > NUMBTHREADS) { printf("Unable to accept client connection! Threads are all used up"); running = false; } else { if(FD_ISSET(sockfd, &readfds)) { if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1) { fprintf(stderr, "Unable to accept client \n"); perror("What"); break; } activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]); //close(bindfd[active_thread]); //pthread_join( threads[active_thread], NULL); active_thread++; //running = false; } } } close(sockfd); return 0; } 

Une partie du code POSIX THREAD

 void *server_handler( void *sockfd) { int bindfd = *( (int *) sockfd); char buffer[MESSAGELENGTH]; bool running = true; printf("Thread was created successfully\n"); char intro[] = "Successfully Connected to server!\n"; struct pollfd pfd; pfd.fd = bindfd; pfd.events = POLLIN; if ( (send(bindfd, intro, strlen(intro), 0)) < 0) { perror("Unable to send"); } while(running){ char msg[] = "\nYou have the following options!\n1) Insert an integer: insert \n2) Remove An Integer: remove \n3) Get number of integers in list: get_count\n4) Get first integer: get_first\n5) Get last integer: get_last\n6) Quit program: quit\n "; if ( (send(bindfd, msg, strlen(msg), 0))  0) { //SOme other code } } 

Je pense que son blocage à l’accepter ou à la recv. J’ai entendu parler de select () et de diverses autres méthodes, mais j’ai du mal à les implémenter. Merci!

La cause fondamentale de votre problème semble être que vous exécutez inconditionnellement close(sockfd); return 0; close(sockfd); return 0; au bas de votre boucle while (running) , ce qui signifie que la boucle ne s’exécute qu’une seule fois.

En outre, vous ne devez pas utiliser FD_ISSET() moins que vous utilisiez également select() . Votre boucle principale devrait ressembler davantage à ceci:

 int active_thread = 0; while (active_thread < NUMBTHREADS) { if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1) { fprintf(stderr, "Unable to accept client \n"); perror("What"); break; } activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]); active_thread++; } if (active_thread >= NUMBTHREADS) { printf("Unable to accept client connection! Threads are all used up.\n"); } running = false; close(sockfd); return 0; 

Par défaut, les sockets réseau bloquent. Vous devez définir le drapeau O_NONBLOCK sur le socket.

 if(fcntl(fd, F_GETFL, &flags) < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) perror("Failed to set socket as non-blocking"); 

Désormais, au lieu de bloquer en l'absence d'entrée (ou d'espace tampon pour stocker la sortie), l'erreur EAGAIN (ou EWOUDLBLOCK) est renvoyée. Enfin, vous devrez utiliser select () ou poll () lorsque vous n'avez rien d'autre à faire que d'attendre les E / S. Ces appels ne réactiveront le processus que si une entrée, une marge de sortie ou éventuellement un délai d'attente est écoulé.

 int maxFd; fdset fds; FD_ZERO(&fds); FD_SET(listenFd, &fds); FD_SET(sockFd1, &fds); FD_SET(sockFd2, &fds); maxFd = listenFd+1; maxFd = sockFd1 > maxFd ? sockFd1+1 : maxFd; maxFd = sockFd2 > maxFd ? sockFd2+1 : maxFd; if(select(maxFd, &fds, &fds, &fds, NULL) < 0) { perror("Failed on select()"); exit(1); } if(FD_ISSET(listenFd, &fds)) ... 

Cet exemple n'est pas complet ou nécessairement correct à 100%, mais devrait être un bon début. De plus, j'ai tendance à réserver en utilisant send * () et recv * () lorsque je traite avec des sockets SOCK_DGRAM et j'utilise simplement read (), write () sur les sockets SOCK_STREAM.