Problèmes de réception de données via un socket client TCP

J’essaie de faire un programme client TCP en C où le client va démarrer, se connecter à un serveur. Ensuite, il enverra un peu d’informations, écoutera ce qu’il recevra et réagira en conséquence.

La partie qui me pose problème est l’écoute continue. Voici ce que j’ai

... while (1) { numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0); buf[numbytes] = '\0'; printf("Received: %s\n", buf); // more code to react goes here } ... 

Lors de la connexion au serveur, après l’envoi de deux lignes de données, le serveur devrait recevoir une bonne quantité d’informations, mais lorsque j’exécute cette opération, il affiche:

Reçu:

Et puis continue à restr assis jusqu’à ce que je le force à fermer.

** EDIT ** quand je fais ce que Jonathan m’a dit de faire, j’obtiens ce qui suit:

Compte: -1, Erreur: 111, Reçu:

Donc, cela signifie que ses erreurs, mais que dois-je faire à ce sujet?

Imprimez le nombre d’octets reçus – il est probable que ce soit zéro, mais confirmez-le.

Il serait bon de vérifier que vous n’obtenez pas d’erreur – et donc que votre mémoire tampon est saturée.

[ Remarque: à partir de maintenant , c’est le travail de Pax – merci , et je l’ai converti en Wiki de la communauté afin que je n’obtienne pas de points de repérage de façon injustifiée. ]

Le code suivant le fera. Essayez et rapportez les résultats, s’il vous plaît.

 while (1) { numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0); buf[numbytes] = '\0'; printf("Count: %d, Error: %d, Received: %s\n", numbytes, errno, buf); // more code to react goes here } 

Après la modification de la question:

Le numéro d’erreur 111 est ECONNREFUSED – ce n’est pas un code d’erreur habituel pour recv (), mais convient davantage à l’appel de type ouvert (open (), connect (), etc.).

Dans tous les cas, ECONNREFUSED est un problème du côté du serveur, pas du client – le serveur a délibérément refusé d’accepter votre connexion entrante. Vous devrez donc examiner cette extrémité du lien.

Afin de tester cela, changez votre code pour qu’il se connecte à http://www.microsoft.com sur le port 80, puis envoyez quelques lignes de tous les vieux déchets. Vous devriez obtenir une erreur de leur serveur Web indiquant une requête HTTP mal formée. Cela prouvera qu’il n’y a pas de problème chez votre client.

Voici ce que je reçois lorsque je telnet www.microsoft.com 80 et que je telnet www.microsoft.com 80 hello suivi de deux fois sur ENTER :

 HTTP/1.1 400 Bad Request Content-Type: text/html; charset=us-ascii Server: Microsoft-HTTPAPI/2.0 Date: Thu, 27 Nov 2008 01:45:09 GMT Connection: close Content-Length: 326  Bad Request  

Bad Request - Invalid Verb


HTTP Error 400. The request verb is invalid.

Vous devriez voir quelque chose de similaire.

Je recommande fortement le Guide de Beej sur la programmation en réseau .

Cette section en particulier a un code pour un client qui fait exactement ce que vous demandez.

EDIT: la réponse ci-dessous était basée sur une incompréhension de la question – le code de l’OP essaye réellement de recv () sur un socket qu’il a ouvert () sur un serveur distant. Trucs en bas à gauche pour la postérité.


S’il vous plaît montrer plus de votre code.

Quelques observations cependant:

  • la prise listen()ing t-elle?
  • avez-vous accept()ed la connexion entrante
  • Il est un peu inhabituel d’utiliser recv() sur un socket TCP. Utilisez read() place.
  • Utilisez strerror() pour convertir le code d’erreur 111 en chaîne d’erreur locale. Chaque système d’exploitation UNIX peut avoir son propre mappage de numéros en codes d’erreur Exxx, de sorte que nous ne pouvons pas savoir quelle est cette erreur sur votre système.

La boucle de code normale (pour une application à un seul thread sans forçage) se présente comme suit:

 s = socket(); err = listen(s, n); // n = backlog number while (1) { int fd = accept(s, &addr, sizeof(addr)); while (1) { int numrecv = read(fd, ...); // break if eof } close(fd); } close(s); 

C’est quoi la boucle infinie? Pourquoi ne pas utiliser select () de manière à n’appeler recv () que lorsque des données réelles doivent être lues?

Dans une vie antérieure, j’avais écrit le code de réseau pour un MUD et je pouvais toujours écrire la boucle d’interrogation dans ma tête. La boucle dans la ROM 2.3 ressemblait à ceci (de mémoire, pardonnez-moi si les parameters de macro sont dans le mauvais ordre):

 #define MAX_CONNECTIONS 256 int main(int argc, char *argv[]) { int i = 0; int running = 1; int connections[MAX_CONNECTIONS]; while( running ) { fd_set in_fd, out_fd, exc_fd; FD_ZERO(in_fd); FD_ZERO(out_fd); FD_ZERO(exc_fd); for( i = 0; i < MAX_CONNECTIONS; i++ ) { if( connections[i] > 0 ) { FD_SET(&in_fd, connections[i]); FD_SET(&out_fd, connections[i]); FD_SET(&exc_fd, connections[i]); } } select(&in_fd, &out_fd, &exc_fd, NULL); // this will block until there's an I/O to handle. for( i = 0; i < MAX_CONNECTIONS; i++ ) { if( FD_ISSET(&exc_fd, connections[i]) ) { /* error occurred on this connection; clean up and set connection[i] to 0 */ } else { if( FD_ISSET(&in_fd, connections[i]) ) { /* handle input */ } if( FD_ISSET(&out_fd, connections[i]) ) { /* handle output */ } } } } }