Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1087 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  taille des buffers de reception d'un recv

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

taille des buffers de reception d'un recv

n°323614
polo021
Posté le 05-03-2003 à 16:13:13  profilanswer
 

Lors de la fonction recv d'une socket, je me demandais ce qui se passerai si le serveur envoyais par exemple 300 char et que mon receive etait prevu pour en recevoir 250.
 
ex : send du server

Code :
  1. char* buffer = "123456789";
  2. send(s, buffer, sizeof(buffer),0);


 
ex : recv du client

Code :
  1. char* buffer;
  2. recv(s,buffer,5*sizeof(char),0);


Est il exacte que je ne vais recevoir que "12345"? Que va-t'il se passer?
 
et maintenant, si le serveur est :

Code :
  1. char* buffer = "12345";
  2. send(s, buffer, sizeof(buffer),0);


 
ex : recv du client

Code :
  1. char* buffer;
  2. recv(s,buffer,9*sizeof(char),0);


Je vais recevoir quoi dans mon buffer?


Message édité par polo021 le 05-03-2003 à 16:19:03
mood
Publicité
Posté le 05-03-2003 à 16:13:13  profilanswer
 

n°323661
pascal_
Posté le 05-03-2003 à 16:52:37  profilanswer
 

polo021 a écrit :

Lors de la fonction recv d'une socket, je me demandais ce qui se passerai si le serveur envoyais par exemple 300 char et que mon receive etait prevu pour en recevoir 250.


 
ex : send du server

Code :
  1. char* buffer = "123456789";
  2. send(s, buffer, sizeof(buffer),0);


 
Buffer est de type char* donc sizeof(buffer)=sizeof(char*)=4 (sur les pc) donc tu vas envoyer 4 caractères
 
Il fallait écrite :

Code :
  1. char* buffer = "123456789";
  2. send(s, buffer, (strlen(buffer)+1) * sizeof(char),0);


 
 
ex : recv du client

Code :
  1. char* buffer;
  2. recv(s,buffer,5*sizeof(char),0);


Est il exacte que je ne vais recevoir que "12345"? Que va-t'il se passer?
 
Ici, recv va écrire à l'addresse mémoire pointée par buffer. Or buffer n'est pas inialisé et pointe donc n'importe où. Il y a de grandes chances que ça plante.
Correction :

Code :
  1. char buffer[256];
  2. recv(s,(void*)buffer,5*sizeof(char),0);


 
Ici, les 5 premiers caractères de buffer serons "12345" suivit ne n'importe quoi (recv n'écrira que dans les 5 premiers caractère)
Si tu veux afficher la chaine, n'oublie pas de rajouter \0 à la fin : buffer[5]='\0';
 
Si tu fais un autre recv juste après, tu recevras la fin de ta chaine : 6789.
 
 
et maintenant, si le serveur est :

Code :
  1. char* buffer = "12345";
  2. send(s, buffer, (strlen(buffer)+1) *sizeof(char),0);


 
ex : recv du client

Code :
  1. char buffer[256];
  2. recv(s,buffer,9*sizeof(char),0);


Je vais recevoir quoi dans mon buffer?
 
La, je ne suis pas sur mais je crois que cela dépend de ta socket, si elle est bloquante ou non.
Si elle est bloquante recv attendra un autre send pour remplir 9 caractère du buffer.
Si elle est non bloquante, je crois que recv te rempli juste 5 caractères et te retoune 5.
Mais le mieux est de lire le manuel de send et recv !!
 
 
 

n°323896
mrbebert
Posté le 05-03-2003 à 20:16:49  profilanswer
 

Dans le cas d'une connexion TCP, il n'y a aucune notion de paquet. L'un des PC envoie une suite d'octets, et l'autre reçoit les même octets, dans l'ordre, mais pas forcément avec les même limites.
Par exemple, si tu envoies 20 octets, puis 10, le client peut très bien recevoir 5 octets, puis 12, puis 13. Le recv() peut également retourner, même s'il n'a pas rempli complètement le buffer.

n°324549
Konar
Posté le 06-03-2003 à 12:47:50  profilanswer
 

Est-ce que ceci est une bonne solution, ou je rate qqchose :
 
on définit une struct ki sera la meme dans le client et le
serveur, par ex :
 

Code :
  1. #define MAX 1024
  2. typedef struct s_Bordel
  3. {
  4.     UINT Size;
  5.     char Data[MAX - 4]; // -4 fote a l'UINT
  6. } t_Bordel;


 
puis dans le serveur on fait des send de cette facon :
 

Code :
  1. t_Bordel Bordel;
  2. string str = "trucs a envoyer";
  3. CopyMemory(Bordel.Data, str.c_str(), str.length());
  4. Bordel.Size = 4 + str.length();
  5. send(s, (char *)&Bordel, Bordel.Size, 0);


 
pour le client, tout le truc chiant c qu'il faut s'attendre
a recevoir des "bouts de paquets". on fait donc des recv() tant
qu'on a pas recu le nb d'octets indiqués au debut de la struct.
 
ca ressemblerait ptet un peu a ca :
 

Code :
  1. t_Bordel Bordel;
  2. int BytesReceived = recv(s, (char*)&Bordel, MAX, 0);


 
Apres on a Bordel.Size ki vaut la taille totale du paquet,
il suffit donc de tester le retour du recv, s'il est plus
petit que Bordel.Size c'est qu'on a pas recu le paquet en
entier, il faut donc refaire un recv() et convaluer le
résultat...
 
mais comme l'a dit Bebert, les résultats sont assez aléatoires,
on recoit souvent des bouts de paquets, voire meme plusieurs
paquets convalués en 1 seul...
 
j'ai fait qq tests chez moi, ca avait l'air de fonctionner
plutot bien, mais si des experts pouvaient me conseiller
autre chose, ils sont les bienvenus...

n°324615
polo021
Posté le 06-03-2003 à 13:35:53  profilanswer
 

voila la solution que j'qi adoptee :  

Code :
  1. char* msg;
  2. if (recv(s,msg, 255*sizeof(msg), 0 )== SOCKET_ERROR )
  3. {
  4.            erreur
  5. }
  6. else
  7. {
  8. AfxMessageBox((CString)msg);
  9. }


 
et ca a l'air de bien fonctionner.
Par contre ce qui ne fonctionne pas c'est  

Code :
  1. char msg[255];
  2. if (recv(s,msg, sizeof(msg), 0 )== SOCKET_ERROR )
  3. {
  4.            erreur
  5. }
  6. else
  7. {
  8. AfxMessageBox((CString)msg);
  9. }


car a l'affichage j'ai des caracteres illegaux a la fin de mon message.
Pensez vous que la premiere solution est une solution fiable si on considere que le serveur envoie toujours des messages de 255 caracteres?

n°324632
Konar
Posté le 06-03-2003 à 14:00:09  profilanswer
 

les 2 solutions sont identiques (les recv sont tous les 2 de 255), a la difference que pour le 1er cas si tu ne malloc pas le 'char *msg' ca risque de seg-folter.
 
ca devrait marcher dans les 2 cas, le seul pb peut venir du '\0' de fin de chaine : si tu envoies "12345" et que tu fais send(s, "12345", 5, 0), lors de ton recv tu n'auras pas le '\0' pour indiquer la fin de chaine. il faut donc faire un send(s, "12345\0", 6, 0) et ca devrait marcher mieux.

n°325049
mrbebert
Posté le 06-03-2003 à 19:16:28  profilanswer
 

Konar a écrit :

Est-ce que ceci est une bonne solution, ou je rate qqchose :
 
on définit une struct ki sera la meme dans le client et le
serveur, par ex :
 

Code :
  1. #define MAX 1024
  2. typedef struct s_Bordel
  3. {
  4.     UINT Size;
  5.     char Data[MAX - 4]; // -4 fote a l'UINT
  6. } t_Bordel;


 
puis dans le serveur on fait des send de cette facon :
 

Code :
  1. t_Bordel Bordel;
  2. string str = "trucs a envoyer";
  3. CopyMemory(Bordel.Data, str.c_str(), str.length());
  4. Bordel.Size = 4 + str.length();
  5. send(s, (char *)&Bordel, Bordel.Size, 0);


 
pour le client, tout le truc chiant c qu'il faut s'attendre
a recevoir des "bouts de paquets". on fait donc des recv() tant
qu'on a pas recu le nb d'octets indiqués au debut de la struct.
 
ca ressemblerait ptet un peu a ca :
 

Code :
  1. t_Bordel Bordel;
  2. int BytesReceived = recv(s, (char*)&Bordel, MAX, 0);


 
Apres on a Bordel.Size ki vaut la taille totale du paquet,
il suffit donc de tester le retour du recv, s'il est plus
petit que Bordel.Size c'est qu'on a pas recu le paquet en
entier, il faut donc refaire un recv() et convaluer le
résultat...
 
mais comme l'a dit Bebert, les résultats sont assez aléatoires,
on recoit souvent des bouts de paquets, voire meme plusieurs
paquets convalués en 1 seul...
 
j'ai fait qq tests chez moi, ca avait l'air de fonctionner
plutot bien, mais si des experts pouvaient me conseiller
autre chose, ils sont les bienvenus...

Ca va pas :o  
Tu envoie des données d'une taille variable (<= MAX), et tu attends jusqu'à recevoir MAX octets. Tu prends le risque de rester indéfiniment en attente de données qui n'arriveront jamais.
Pour la réception, il me parait préférable de lire le UINT seul, puis de lire le nombre d'octets correspondants.
 
Pour le problème du '\0' terminal, c'est à toi de voir. Soit tu l'envoie, soit tu l'envoie pas, mais il faut que l'émetteur et le récepteur soient d'accord.


Message édité par mrbebert le 06-03-2003 à 19:20:08
n°325885
Konar
Posté le 07-03-2003 à 12:27:06  profilanswer
 

mrBebert a écrit :

Ca va pas :o  
Tu envoie des données d'une taille variable (<= MAX), et tu attends jusqu'à recevoir MAX octets. Tu prends le risque de rester indéfiniment en attente de données qui n'arriveront jamais.
Pour la réception, il me parait préférable de lire le UINT seul, puis de lire le nombre d'octets correspondants.
 
Pour le problème du '\0' terminal, c'est à toi de voir. Soit tu l'envoie, soit tu l'envoie pas, mais il faut que l'émetteur et le récepteur soient d'accord.


 
pas tout a fait : en fait dans le recv, le MAX indique juste la taille maximale pouvant etre recue, et non la taille qui DOIT etre recue. recv retournera le nb d'octets qu'il a mis dans le buffer.
 
le 3eme parametre du recv (MAX) indique juste la taille maximale du buffer. D'apres les man : "If the datagram or message is larger than the buffer supplied, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE."
 
pour le '\0', c juste pour les gens ki envoient des phrases, et dans leur cas il suffit de faire un ZeroMemory sur leur buffer.
(moi j'envoie du binaire, donc j'ai pas ce pb).
 
par contre pour ta solution de faire un recv de 4 pour recevoir juste l'UINT, puis un autre recv avec la taille correspondante, c pas con, je vais tester ca...
 
a+

n°326310
mrbebert
Posté le 07-03-2003 à 19:21:38  profilanswer
 

Konar a écrit :


 
pas tout a fait : en fait dans le recv, le MAX indique juste la taille maximale pouvant etre recue, et non la taille qui DOIT etre recue. recv retournera le nb d'octets qu'il a mis dans le buffer.
 
le 3eme parametre du recv (MAX) indique juste la taille maximale du buffer. D'apres les man : "If the datagram or message is larger than the buffer supplied, the buffer is filled with the first part of the datagram, and recv generates the error WSAEMSGSIZE."
 
pour le '\0', c juste pour les gens ki envoient des phrases, et dans leur cas il suffit de faire un ZeroMemory sur leur buffer.
(moi j'envoie du binaire, donc j'ai pas ce pb).
 
par contre pour ta solution de faire un recv de 4 pour recevoir juste l'UINT, puis un autre recv avec la taille correspondante, c pas con, je vais tester ca...
a+

Ca ne correspond pas plutot à de l'UDP :heink:  
 
Je parle du cas où les données reçues sont de taille < MAX. Lorsque ta socket est bloquante, elle va attendre d'avoir des données en plus. Alors qu'aucune autre donnée n'arrivera.
Bien sur, on peut supposer qu'au bout d'un moment, elle se terminera quand même. Mais ce n'est pas garantit.
Tu prends donc le risque d'avoir un programme qui reste bloqué à attendre des données qui n'arriveront jamais :/


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  taille des buffers de reception d'un recv

 

Sujets relatifs
[php] limiter la taille des img en upload[Flash] Taille du texte dynamique
problème taille de buffer /socket[CSS/HTML] Ya moyen de changer la taille de la scrollbar ???
[DBGrid] Taille du déplacement horizontal ?[C++] tronquer un fichier à une certaine taille
[delphi]Taille de fenêtre[vb] Taille max d un champ texte
Taille d'un fichier distant[HTML] tableau de taille maximale pour un forum
Plus de sujets relatifs à : taille des buffers de reception d'un recv


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR