Plusieurs appels à send () sont fusionnés en un seul appel à recv ()

J’ai une application client-serveur.

Le client envoie une chaîne suivie d’un entier à l’aide de deux appels send() distincts. Ces deux données sont supposées être stockées dans deux variables différentes sur le serveur.

Le problème est que les deux variables envoyées sont reçues lors de l’appel de recv() . Par conséquent, les deux chaînes envoyées par les deux send() distincts sont chaînées et stockées dans la mémoire tampon du premier recv() .

server.c:

 printf("Incoming connection from client %s:%i accepted\n",inet_ntoa(clientSocketAddress.sin_addr),ntohs(clientSocketAddress.sin_port)); memset(buffer,0,sizeof(buffer)); int sizeofMessage; if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0)==sizeofMessage)<0) { printf("recv failed."); closesocket(serverSocket); clearWinsock(); return EXIT_FAILURE; } char* Name=buffer; printf("Name: %s\n",Name); if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0))<0) { printf("bind failed."); closesocket(serverSocket); clearWinsock(); return EXIT_FAILURE; } int integer=ntohs(atoi(buffer)); printf("integer: %i\n",intero); 

client.c:

 if (send(clientSocket,Name,strlen(Name),0)!=strlen(Name)) { printf("send failed"); closesocket(clientSocket); clearWinsock(); return EXIT_FAILURE; } printf("client send: %s",Name); int age=35; itoa(htons(age),buffer,10); sizeofBuffer=strlen(buffer); if (send(clientSocket,buffer,sizeofBuffer,0)!=sizeofBuffer) { printf("bind failed."); closesocket(clientSocket); clearWinsock(); return EXIT_FAILURE; } 

Comment puis-je le réparer? Qu’est-ce que je fais mal?

TCP est un protocole de streaming. Il n’a connaissance d’aucune sorte de frontière de “message”. Il n’ajoute pas que de telles informations dépendent d’appels uniques à send() .

En raison de ces faits, n’importe quel nombre de send() du côté de l’expéditeur peut conduire à un nombre quelconque de recv() (du nombre d’octets envoyés) (du nombre maximal d’octets envoyés) du côté du destinataire.

Pour contourner ce problème, définissez et implémentez un protocole au niveau de l’application afin de distinguer les différents «messages» qui ont été envoyés.

On ne peut pas compter sur recv() / send() recevoir / envoyer autant d’octets que ces deux fonctions ont reçu l’ordre de recevoir / envoyer. Il est indispensable de vérifier leur valeur de retour pour connaître le nombre d’octets réellement reçus / envoyés par ces fonctions et de les contourner jusqu’à ce que toutes les données destinées à être reçues / envoyées aient été reçues / envoyées.

Par exemple, comment ce “bouclage” pourrait être fait

Voici comment fonctionne TCP. Traitez-le comme un stream d’octets. Ajoutez un protocole de base – délimitez les messages d’application avec une valeur d’octet connue ou ajoutez-y des champs avec un champ de longueur.

Ou passez en UDP, qui vous donne la sémantique de datagramme que vous recherchez, si vous pouvez tolérer / récupérer après une perte de paquet occasionnelle.