Comment envoyer et recevoir le socket de données TCP (C / C ++)

Dupliquer possible:
Quelle est la bonne façon de lire un socket TCP en C / C ++?

J’essaie de développer un client / serveur TCP. Mon problème est que, lorsque j’essaie d’envoyer les données de client, je le fais en un seul envoi.

Mais mon problème apparaît lorsque j’essaie de recevoir les données avec une structure spécifique, les 8 premiers octets définissant une date, les 10 suivants un nom et le nombre indéfini d’octets définissant un texte (ce texte se termine par / r / n / r / n)

Le client envoie comme suit:

char date[8]; char name[10]; char msg[4096]; strcpy(msg,"12/10/12"); //8 bytes strcat(msg,"Kevin Fire"); //10 bytes strcat(msg,"abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde\r\n\r\n"); nbytes_sent = send(sock,(char *)msg,sizeof(msg),0); printf("Bytes_sent: %s -> %i\n",msg,nbytes_sent); 

Et le serveur essaie d’parsingr les données du socket comme suit:

 char date[8]; char name[10]; char * text; char buf[1024]; int i=0; for(i=0; i < 8; i++) date[i] = '\0'; for(i=0; i  0){ printf("Date: %s (%i)\n",date,nbytes_read); //cout.flush(); nbytes_read=recv(sclient,(char *)name,sizeof(name),0); if(nbytes_read > 0){ printf("Name: %s (%i)\n",name,nbytes_read); //cout.flush(); nbytes_read=recv(sclient,(char *)buf,sizeof(buf),0); strcpy(text,buf); while(nbytes_read > 0){ nbytes_read=recv(sclient(char*)buf,sizeof(buf),0); strcat(text,buf); } } } printf("Date: %s. Name: %s. Text: %s\n",date,name,text); 

Voici une simple fonction “recevoir tout”:

 int recv_all(int sockfd, void *buf, size_t len, int flags) { size_t toread = len; char *bufptr = (char*) buf; while (toread > 0) { ssize_t rsz = recv(sockfd, bufptr, toread, flags); if (rsz <= 0) return rsz; /* Error or other end closed cnnection */ toread -= rsz; /* Read less next time */ bufptr += rsz; /* Next buffer position to read into */ } return len; } 

Une erreur (répétée) est:

 nbytes_read=recv(sclient,(char *)date,sizeof(date),0); 

recv() ne termine pas à zéro. Cela signifie que la date n’aura pas de terminateur NULL si sizeof(date) octets est lu. Cela pose un problème lorsqu’une chaîne terminée par une valeur non nulle est transmise en tant qu’argument à printf() avec le spécificateur de format "%s" . Si la chaîne est terminée avec une valeur NULL, il est possible que des caractères parasites apparaissent après les données de chaîne réelles. Vous devez en lire un de moins que le tampon cible et la terminaison NULL ou utiliser le spécificateur de format "%*.s" qui ne nécessite pas de terminaison NULL:

 printf("%.*s", n, s); /* Prints first 'n' bytes from 's'. */ 

Notez que vous pouvez initialiser un caractère char[] à tous les caractères nuls au lieu d’utiliser un for :

 char date[8] = ""; 

ou vous pouvez utiliser memset() .

Ajout à la recherche de @ hmjd:

déclaré à la var decls est votre pointeur de texte …

 char * text; 

puis plus tard …

 strcpy(text,buf); while(nbytes_read > 0){ nbytes_read=recv(sclient(char*)buf,sizeof(buf),0); strcat(text,buf); } 

Essayez peut-être d’append un pointeur de texte à une valeur de stack aléatoire.

Poursuivant le barrage, même si les éléments suivants ne vont pas nécessairement exploser, votre variable de date sera la suivante:

 char date[8]; 

côté client et côté serveur La variable client n’est pas du tout utilisée. La variable serveur est cependant:

 nbytes_read=recv(sclient,(char *)date,sizeof(date),0); if(nbytes_read > 0){ 

Le problème, c’est que la date d’envoi est en fait déjà large de 8 caractères: “12/10/12”. Par conséquent, même si vous fixez un terminateur null à la fin de votre chaîne, vous devriez toujours le faire malgré tout (bonne pratique):

 date[ sizeof(date)/sizeof(date[0])-1 ] = 0; 

vous allez tronquer le dernier caractère de votre date.

Il y a d’autres problèmes avec cela; nous n’en avons signalé que quelques-uns. Pensez à envoyer des préfixes de longueur avec chacune de ces valeurs de données dans le tableau, avec des vérifications ou une plage pour vous assurer d’obtenir ce que vous attendiez.

Enfin, consacrer un peu de temps à l’exploitation d’un débogueur vous conviendrait probablement très bien, en particulier du côté du serveur.