[resolu]Socket reception de 0

Socket reception de 0 [resolu] - C - Programmation

Marsh Posté le 29-05-2009 à 11:11:08    

Bonjour,
 
voilà je me heurte à un problème d'envoi par l'intermédiaire de socket. Je souhaite en effet envoyer la valeur des pixels d'une image (compris entre 0 et 255) mais dés que cette valeur est à 0 je rencontre des problèmes pour récupérer mes données. Comment faire pour indiquer à la fonction recv() qu'elle ne doit pas prendre en compte les caractères EOF et ne s'intéresser qu'à la taille du buffer que je lui ai mis en paramètre et de s'arrêter une fois qu'il est plein?  
 
Merci

Message cité 1 fois
Message édité par Zenshu le 29-05-2009 à 15:05:57
Reply

Marsh Posté le 29-05-2009 à 11:11:08   

Reply

Marsh Posté le 29-05-2009 à 12:03:43    

1. Le titre du sujet contient le mot "envoi", qui se fait normalement par sendto et non pas par recv qui est pour la réception. Cela dit, dans les deux cas, il ne devrait pas y avoir de problème avec le caractère binaire zéro.
 
2. La fonction recvfrom() remplit un buffer sans se soucier du type de caractère. Elle met les caractères alphanumérique et tous les caractères binaires non imprimables qu'elle reçoit, sans distinction. Donc, je soupçonne que le problème est ailleurs.
 
3. La taille du buffer donnée à la fonction recvfrom() est une taille maximale. Cela indique de ne pas faire de débordement.


Message édité par olivthill le 29-05-2009 à 12:09:36
Reply

Marsh Posté le 29-05-2009 à 12:17:32    

1. c'est vrai j'ai fait une erreur dans le titre. Pour l'envoi j'utilise la fonction send(), il vaut mieux utilisé sendto()?  
 
2. J'espère que le problème est ailleurs mais lorsque que j'envoie des caractères autre que des 0 je n'ai pas de problèmes pour les réceptionner. Donc je  soupçonnait recv() d'être la cause de mon problème.
 
3. ok

Reply

Marsh Posté le 29-05-2009 à 12:24:15    

Désolé, j'ai pris mon cas pour une génréalité, car j'utilise sendto() et recvfrom(), mais c'est vrai qu'on peut aussi utiliser send() et recv(). Ces deux dernières fonctions, send() et recv(), ne sont pas non plus sensibles au caractère binaire zéro, ni aux autres caractères.

Reply

Marsh Posté le 29-05-2009 à 13:06:36    

pourtant lorsque j'envoie avec send() et que je verifie la valeur retournée par cette fonction je vois bien que l'intégralité des octets ont été envoyé. Ca ne peut être donc qu'à la lecture que le problème se pose.
Lorsque que j'envoie un tableau de 76800 cases remplie avec une suite de nombre allant de 0 à 255 je me retrouve avec un tableau rempli de 0 alors que lorsque j'envoie une suite de nombre allant de 1 à 255 ça marche!  
L'ensemble de mes valeurs sont stockées dans un char *.

Reply

Marsh Posté le 29-05-2009 à 13:40:44    

En étant pointilleux, je dirais qu'un char * ne contient que 4 ou 8 octets selon que l'on est en mode 32-bit ou 64-bit car un char * n'est qu'un pointeur. La zone de mémoire allouée à l'adresse pointée par ce pointeur est plus intéressante que le pointeur.
Sans voir le code, il est difficile de trouver la raison du problème. Pour rappel, voici quelques fonctions qui sont sensibles au caractère null : strlen(), strcpy(), strcat(), sprintf(), scanf().

Reply

Marsh Posté le 29-05-2009 à 13:50:51    

Pour l'instant je travaille en local en mode 32 bits.
 
voici la partie client:
 

Code :
  1. unsigned char *buffer;
  2. buffer=calloc(MAX,sizeof(char));
  3. if(buffer==NULL)
  4. {
  5.  perror("problème allocation" );
  6.  exit(EXIT_FAILURE);
  7. }
  8. else
  9.  printf("allocation réussie\n" );
  10. for(j=0; j<MAX;++j)
  11. {
  12.  *(buffer+j)=(char)((j%255));
  13.  //printf("%x \n", *(buffer+j));
  14. }
  15. taille_img=IMG_SIZE; //type int
  16.  
  17.     .
  18.     .
  19.     .
  20. /*Partie envoi*/
  21. if((nb_s=send(sock, &taille_img, sizeof(int),0))!=SOCKET_ERROR)
  22. {
  23. printf("envoi réussi de %d octets\n", nb_s);
  24. }
  25. else printf("Impossible d'envoyer taille du tableau\n" );
  26. if((nb_s=send(sock, buffer, MAX,0))!=SOCKET_ERROR)
  27. {
  28. printf("envoi réussi de %d octets sur %d\n", nb_s, MAX);
  29. }
  30. else printf("Impossible d'envoyer message\n" );


 
Partie serveur:
 

Code :
  1. do
  2.     {
  3.      if((nb_lu=recv(csock,tmp, MAX_BUF*sizeof(char),MSG_PEEK))!= SOCKET_ERROR)
  4.      {
  5.       printf("\n************message reçu************\n" );
  6.       printf("\nlecture de %d octets\n", nb_lu);
  7.       /*if(buffer!=NULL)
  8.       {
  9.        free(buffer);
  10.        buffer=NULL;
  11.       }*/
  12.       buffer=(char *)malloc(nb_lu*sizeof(char));
  13.       if(buffer==NULL)
  14.       {
  15.        perror("problème allocation" );
  16.        exit(EXIT_FAILURE);
  17.       }
  18.       else printf("allocation réussie du buffer: taille= %d \n", nb_lu);
  19.       if((nb_lu=recv(csock,buffer, nb_lu*sizeof(char),0))!= SOCKET_ERROR)
  20.       {
  21.        reste-=nb_lu;
  22.        printf("longueur du buffer %d\n", strlen(buffer));
  23.        snprintf(image+dec,taille_img, "%s",buffer);
  24.        printf("decalage = %d\n",dec);
  25.        printf("longueur de l'image %d\n", strlen(image));
  26.        printf("longueur du buffer %d\n", strlen(buffer));
  27.        dec+=nb_lu;
  28.       }
  29.       else
  30.       {
  31.        perror("le message n'a pas ete reçu 2\n" );
  32.        exit(EXIT_FAILURE);
  33.       }
  34.      }
  35.      else
  36.      {
  37.       perror("le message n'a pas ete reçu 3\n" );
  38.       exit(EXIT_FAILURE);
  39.      }
  40.     }
  41.     while(reste);


 
La partie serveur récupère donc le message en plusieurs passes et le concatène dans un char *image au fur et à mesure.
 

Reply

Marsh Posté le 29-05-2009 à 13:55:06    

strlen() !!! (le décompe des octets s'arrête au premier zéro binaire trouvé)
Edit : et snprintf(...%s...) !!! (l'affichage des octets s'arrête au premier zéro binaire trouvé)


Message édité par olivthill le 29-05-2009 à 14:02:36
Reply

Marsh Posté le 29-05-2009 à 14:38:40    

aahhhh ok! :(
comment je peux afficher la taille de mon buffer si il n'est remplie que de zero?
 
tu n'aurais pas une idée de la fonction que je pourrais utiliser pour concaténer mes chaînes alors? je viens de regarder pour strncpy et j'ai bien l'impression qu'elle s'arrête également au caractère EOF.

Reply

Marsh Posté le 29-05-2009 à 14:47:37    

En étant pointileux encore, EOF n'est pas le bon terme, car EOF veut dire End of File et il n'y apas de fichier ici. De plus ce caractère EOF est parfois le control Z qui vaut 26 en binaire, et pas zéro. Donc, il vaut mieux parler du zéro binaire, ou du caractère nul.
 
Pour connaitre la taille du contenu du buffer, c'est nb_lu=recv(...).
Pour la taille du bloc envoyé, il est impossible de la connaître. C'est pourquoi, habituellement, on envoi d'abord un nombre fixe d'octets (par exemple 8) contenant la taille du bloc qui va être envoyé derrière.
 
Pour la concaténation, sprintf() peut être utilisé, mais pas avec un "%s". A la place, il y a une syntaxe où l'on met la longueur maximale entre "%" et le "s", et on rajoute parfois un point ou un signe moins, et parfois une étoile. Je ne me souviens plus de la syntaxe exacte. Voir la documentation. Personnellement, je fais une petite boucle en traitant caractère par caractère, comme ça c'est plus simple et au moins aussi rapide (car sprintf() ou d'autres fonctions font aussi des boucles qui ne vont pas plus vite).


Message édité par olivthill le 29-05-2009 à 14:51:25
Reply

Marsh Posté le 29-05-2009 à 14:47:37   

Reply

Marsh Posté le 29-05-2009 à 14:57:09    

Citation :


 En étant pointileux encore, EOF n'est pas le bon terme, car EOF veut dire End of File et il n'y apas de fichier ici. De plus ce caractère EOF est parfois le control Z qui vaut 26 en binaire, et pas zéro. Donc, il vaut mieux parler du zéro binaire, ou du caractère nul.  


 
ok
 

Citation :


Pour connaitre la taille du contenu du buffer, c'est nb_lu=recv(...).
Pour la taille du bloc envoyé, il est impossible de la connaître. C'est pourquoi, habituellement, on envoi d'abord un nombre fixe d'octets (par exemple 8) contenant la taille du bloc qui va être envoyé derrière.  


 
C'est ce que je fais, j'envoie un int contenant le nombre d'octet que j'envoie et je m'en sers pour allouer la mémoire de mon buffer "image" dans lequel je recompose mon image. je vais me renseigner sur les options du sprintf et autrement je ferais une boucle.  
 
merci

Reply

Marsh Posté le 29-05-2009 à 15:05:23    

bon le choix a été rapide, une petite boucle et on parle plus! :)
 
merci beaucoup

Reply

Marsh Posté le 30-05-2009 à 19:56:42    

Zenshu a écrit :

voilà je me heurte à un problème d'envoi par l'intermédiaire de socket. Je souhaite en effet envoyer la valeur des pixels d'une image (compris entre 0 et 255) mais dés que cette valeur est à 0 je rencontre des problèmes pour récupérer mes données. Comment faire pour indiquer à la fonction recv() qu'elle ne doit pas prendre en compte les caractères EOF et ne s'intéresser qu'à la taille du buffer que je lui ai mis en paramètre et de s'arrêter une fois qu'il est plein?  


http://www.bien-programmer.fr/reseaux.htm#binaire
 
Nota :  
- En mode connecté (TCP, par exemple) : send() / recv()
- En mode non-connecté (UDP, par exemple) : sendto() / recvfrom()
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed