Données de socket corrompues lors du transfert TCP / IP

Lorsque j’envoie des données via un socket TCP-IP pré-connecté, je constate que les données sont corrompues.

Exemple:

Station1 envoie des données à Station2. J’ai imprimé les données avant l’envoi (en S1) et après la réception (en S2). Ci-dessous le message:

S1: les données envoyées sont ACK
S2: Les données reçues sont AC

Je ne sais pas quel est le problème. J’ai même effacé le char-buffer avant d’envoyer les données (à S1) et avant de recevoir (à S2).

Toute indication / information pour ce qui précède serait d’une grande aide.

Ceci est généralement le résultat de quelque chose comme:

 /* BAD CODE */ const char* ack = "ACK"; err = write( sockfd, ack, strlen( ack )); /* sender */ /* ... */ char buf[SOME_SIZE] readb = read( sockfd, buf, SOME_SIZE ); /* receiver */ printf( "%s", buf ); 

Le problème avec le code ci-dessus est que l’expéditeur n’écrit que trois (3) octets dans le socket. Cela n’inclut pas la chaîne zéro-terminateur. Ensuite, le destinataire récupère les données et ne vérifie pas la valeur de retour d’appel système ou / et imprime en aveugle les données reçues. Le printf imprimera tout jusqu’à trouver un octet de valeur zéro en mémoire.

Modifier:

Sur la base de vos commentaires, je pense que vous supposez qu’un send(2) sur un socket TCP devrait donner un recv(2) à l’autre extrémité avec le nombre correspondant d’octets (je suppose que c’est ce que vous entendez par “nombre d’octets lire se tromper “). Ce n’est cependant pas le cas avec TCP. Vous devez traiter le socket comme un stream pouvant vous donner des fragments de taille arbitraire de ce qui vous a été envoyé. C’est à vous de les rassembler et de reconnaître les limites des messages d’application. Cela signifie simplement que vous lisez toujours depuis une socket dans une boucle (sans compter les conceptions non bloquantes avec select(2) et amis – c’est un sujet séparé).

Les deux protocoles de protocole d’application acceptés sont les suivants:

  • Communiquez via des messages de longueur fixe prédéfinis – vous pourrez ainsi lire jusqu’à obtenir autant d’octets de la socket. Simple.
  • Incluez le type de message et / ou la longueur du message dans le message lui-même – cela se fait généralement avec un en-tête de message de longueur fixe suivi d’une charge utile variable. Lisez jusqu’à obtenir un en-tête complet, puis changez / envoyez / continuez la lecture en fonction du type / de la longueur.

N’oubliez pas endianess – les réseaux tels que l’ ordre des octets du réseau .

Êtes-vous sûr de recevoir tout le message en une fois? Puisque TCP est un protocole basé sur un stream, les données que vous lisez sur Station2 peuvent entrer dans de petites quantités de données. Vous devez regarder combien de données la fonction recv () met dans votre tampon.

Par exemple, votre premier appel à recv () peut donner “AC”, puis le prochain appel peut vous donner le rest des données “K”

Du côté du client, j’envoie une chaîne à un socket:

 char message[200]; /*ssortingng to be sent*/ strcpy(message, "Hi PQRS, How are you!?"); /*send ssortingng to server's socket*/ if( send(socket_desc , message , strlen(message)+1 , 0) < 0) { puts("Send failed"); return 1; } puts("Data Sent\n"); 

Remarquez comment je passe

'strlen (message) + 1'

pour permettre le délimiteur c'est-à-dire '\ 0' au lieu de

'strlen (message)'

Cela garantit la fin de la chaîne et qu'aucune donnée supplémentaire n'est ajoutée.

Cela fonctionnerait quelle que soit la taille du tableau de caractères côté serveur, à condition qu'il soit supérieur ou égal à la chaîne entrante afin de l'adapter.