"vider" une socket

"vider" une socket - C++ - Programmation

Marsh Posté le 20-03-2003 à 09:02:25    

bonjour,  
 
lorsque mon programme client envoie une requete au programme serveur, il arrive parfois que le send fonctionne mais pas le recv. Donc quand je reenvoie ma demande une deuxieme fois et que le recv fonctionne j'ai deux fois ma reponse dans le buffer de reception.
 
Existe t'il un moyen quelconque pour "vider" les informations contenues dans la socket avant de faire un recv? afin de ne pas avoir deux fois la reponse.
 
Merci

Reply

Marsh Posté le 20-03-2003 à 09:02:25   

Reply

Marsh Posté le 20-03-2003 à 09:03:43    

Il faut faire attention à vider le buffer de réception avant chaque recv. Un petit strcpy(buf, "" ); et voila !

Reply

Marsh Posté le 20-03-2003 à 09:09:53    

ANTSite a écrit :

Il faut faire attention à vider le buffer de réception avant chaque recv. Un petit strcpy(buf, "" ); et voila !


 
Est ce que tu est sur que ca suffira?
 
Parce que quand mon recv ne fonctionne pas, le serveur de son cote a quand meme envoye les donnees. Et si mon recv n'a pas fonctionne je pensais que ca voulais dire que les donnees etaient encore dans la socket et non pas dans le buffer. Est ce possible?

Reply

Marsh Posté le 20-03-2003 à 09:59:44    

polo021 a écrit :


 
Est ce que tu est sur que ca suffira?
 
Parce que quand mon recv ne fonctionne pas, le serveur de son cote a quand meme envoye les donnees. Et si mon recv n'a pas fonctionne je pensais que ca voulais dire que les donnees etaient encore dans la socket et non pas dans le buffer. Est ce possible?


 
Oui, je confirme. Je viens d'avoir un recv qui ne s'est pas effectue et malgre la remise a blanc de mon buffer de reception, j'ai quand meme recu les donnees deux fois au recv suivant!

Reply

Marsh Posté le 20-03-2003 à 11:19:56    

J'ai eu l'occasion d'utiliser pas mal les sockets sous Windows (et un peu sous FreeBSD) et je n'ai jamais eu de problèmes de ce type.
 
Il faudrait que tu précise un peu dans quelles conditions ça se produit (OS utilisés, type de socket, lien utilisé entre le serveur et le client, fréquence d'apparition du problème...), et peut être fournir un peu de code.
 
Cependant, j'ai l'intuition que ton problème ne se situe pas au niveau des sockets mais plus de ton programme (ou de ta compréhension du fonctionnement des sockets). En effet, ton information est bien transférée du client vers le serveur (le deuxième recv le montre bien).
Si tu utilises des sockets "fiables" (par exemple TCP/IP), tu peux être sûr que l'information va atteindre sa destination (évidemment sauf si les sockets te renvoie une erreur). Tu n'as donc jamais besoin de renvoyer une information.
Si tu utilises des sockets "non-fiables" (par exemple UDP/IP), tu n'es pas sûr que l'information va atteindre sa destination. Mais ça ne doit pas causer de problèmes pour ton application. Si c'est un problème, il vaut mieux utiliser des sockets "fiables" plutôt que de réinventer la roue.


---------------
each day I don't die is cheating
Reply

Marsh Posté le 20-03-2003 à 12:36:45    

pour vider ce qui est en attente tu peut faire un recv (lol)
 
pourquoi et comment tu decides que le client doit renvoyer l'info au server ?
tu peux aussi établir un protocol d'echange avec accusé de rception

Reply

Marsh Posté le 20-03-2003 à 15:58:37    

Code :
  1. WSAStartup(0x0101,&wsadata);
  2. s = socket( AF_INET, SOCK_STREAM, 0 );


 
voici le code du recv

Code :
  1. if (ret=recv(s,msg2, 2048*sizeof(char), 0 )== SOCKET_ERROR )
  2.  {
  3.   AfxMessageBox((CString)"recv not ok" );
  4.   return '\0';
  5.  }
  6.  else
  7.  {
  8.   AfxMessageBox((CString)"recv ok" );
  9.   AfxMessageBox((CString)msg2);
  10.   return(msg2);
  11.  }


 
En effet, je dois avoir des problemes avec mon programme car parfois l'instruction recv ne se fait meme pas.
Mais comment se fait il que parfois le 1er recv ne fonctionne pas et que les suivants fonctionnent? Je fais pourtant appel a chaque fois a la meme fonction de mon application.  :(  
 
Et puis parfois aussi quand je fais un send d'un message (ex : 123-45678901), ca fonctionne a tous les coups (send et recv) mais quand je fais un send de 123-01987654, le send fonctionne mais pas le recv. Le format est pourtant identique. Vous n'avez jamais connu ca?
 
 
 

Reply

Marsh Posté le 20-03-2003 à 16:08:52    

Et on code du send c koi ?
(l init socket et le buffer + send)

Reply

Marsh Posté le 20-03-2003 à 17:10:46    

VisualC++ a écrit :

Et on code du send c koi ?
(l init socket et le buffer + send)


pour le client

Code :
  1. if (send( s, msg, strlen(msg), 0 )== SOCKET_ERROR )
  2. {
  3.  AfxMessageBox((CString)"send not ok" );
  4.  return(false);
  5. }
  6. else
  7. {
  8.  AfxMessageBox((CString)"send ok" );
  9.  return (true);
  10. }


Code :
  1. if(connect( s, ( LPSOCKADDR ) &gw_addr, sizeof( gw_addr ) ) == SOCKET_ERROR )


les buffers, c'est a chaque fois  
        char* truc
 
si tu demandais la source du send du server, je ne l'ai pas.
 

Reply

Marsh Posté le 20-03-2003 à 17:10:50    

Quand tu fais un recv ou un send, tu dois non seulement t'assurer qu'il n'y a pas eu d'erreurs mais aussi que tout a été envoyé (ou reçu). En effet, tu peux vouloir envoyer (ou recevoir) 32 octets et qu'en fait il y en ait eu juste 16 d'envoyé (ou de reçu).
Je ne suis pas sûr que ce soit réellement important mais rien ne dit que ça ne puisse pas arriver.


Message édité par gatorette le 20-03-2003 à 17:16:14

---------------
each day I don't die is cheating
Reply

Marsh Posté le 20-03-2003 à 17:10:50   

Reply

Marsh Posté le 20-03-2003 à 17:15:39    

gatorette a écrit :

Quand tu fais un recv ou un send, tu dois non seulement t'assurer qu'il n'y a pas eu d'erreurs mais aussi que tout a été envoyé (ou reçu). En effet, tu peux vouloir d'envoyer (ou recevoir) 32 octets et qu'en fait il y en ait eu juste 16 d'envoyé (ou de reçu).


 
la taille des messages que le client recoit est variable mais jamais plus grande que 2048.
C'est vrai que je ne me suis pas assure que tout etait envoyem je v le faire. Merci

Reply

Marsh Posté le 20-03-2003 à 17:21:08    

vi /agree
 
Aussi strlen() ok mais tu es sur que c que des chaines de car qui sont envoyee et bien terminee par \0 ?
 

Code :
  1. int iToSend = strlen(msg); // ou sizeof suivant si t es sur de ton buffer ou pas
  2. int iSent =send( s, msg, iToSend, 0);
  3. if ((iSent == SOCKET_ERROR ) || (iSent != iToSend)) {
  4.     AfxMessageBox(CString("send not ok" ));
  5.     return(false);
  6. }
  7. else {
  8.     AfxMessageBox(CString("send ok" ));
  9.     return (true);   
  10. }


 
Puis je te redit CString("" ) c mieu que (CString)"" ;)

Reply

Marsh Posté le 20-03-2003 à 17:26:13    

Tu peux aller voir les exemples de code dans la faq Winsock.
 

polo021 a écrit :

Code :
  1. if (ret=recv(s,msg2, 2048*sizeof(char), 0 )== SOCKET_ERROR )
  2.  {
  3.   AfxMessageBox((CString)"recv not ok" );
  4.   return '\0';
  5.  }
  6.  else
  7.  {
  8.   AfxMessageBox((CString)"recv ok" );
  9.   AfxMessageBox((CString)msg2);
  10.   return(msg2);
  11.  }



 
Hors-Sujet : Renvoyer des pointeurs créés localement, je ne crois pas que ce soit bien. En effet, dès que tu sors de sa portée, rien ne te garanti que le pointeur ne va pas être modifié.
 

polo021 a écrit :

Et puis parfois aussi quand je fais un send d'un message (ex : 123-45678901), ca fonctionne a tous les coups (send et recv) mais quand je fais un send de 123-01987654, le send fonctionne mais pas le recv. Le format est pourtant identique. Vous n'avez jamais connu ca?


 
Non, peut être un bug provoqué par ton autre bug...


---------------
each day I don't die is cheating
Reply

Marsh Posté le 20-03-2003 à 17:31:42    

VisualC++ a écrit :


Puis je te redit CString("" ) c mieu que (CString)"" ;)


 
t'inquites pas, j'applique les conseils qui me sont donnes mais il s'agit la d'une partie plus ancienne de mon pgm et ou je n'ai pas pense a modifier mes AfxMessageBox.
 
Pour le reste je v essayer demain car j'ai un bus dans 5 minutes.
Merci a+

Reply

Marsh Posté le 20-03-2003 à 19:48:53    

C'est peut être tout simplement un problème de taille de données reçues et attendues.
J'explique : en TCP, il n'y a pas de notion de limite de paquet. Si tu envoie 7 octets puis 9 autres, tu as envoyé 16 octets, sans savoir comment il sont séparés. Le recv peut très bien considéré qu'il a reçu 5 octets, puis 8 autres, puis encore 3 autres.
 
De plus, lorsque le recv est bloquant, il attend des données. Tant que son buffer n'est pas plein, il peut attendre.
Dans ton cas, ton recv attends 2048 octets. Tant qu'il ne les a pas reçus, il peut attendre [:proy]

Reply

Marsh Posté le 20-03-2003 à 20:00:41    

mrBebert a écrit :

C'est peut être tout simplement un problème de taille de données reçues et attendues.
J'explique : en TCP, il n'y a pas de notion de limite de paquet. Si tu envoie 7 octets puis 9 autres, tu as envoyé 16 octets, sans savoir comment il sont séparés. Le recv peut très bien considéré qu'il a reçu 5 octets, puis 8 autres, puis encore 3 autres.
 
De plus, lorsque le recv est bloquant, il attend des données. Tant que son buffer n'est pas plein, il peut attendre.
Dans ton cas, ton recv attends 2048 octets. Tant qu'il ne les a pas reçus, il peut attendre [:proy]  


 
comment est ce qu'il faudrait que je modifier mon programme alors pour etre sur de la taille a recevoir? Puisqu'elle peut etre variable. Il y a une solution?

Reply

Marsh Posté le 20-03-2003 à 20:12:25    

Tu peux faire en sorte de faire précéder chaque message par sa taille en octets (dans un entier).
Ainsi, tu lis d'abord l'entier (tu connais sa taille), puis les données (tu as leur taille) :)  
 
Ou alors, tu fais en sorte que tout les messages aient la même taille (mais ca risque de consommer inutilement de la bande passante :/ )

Reply

Marsh Posté le 20-03-2003 à 20:16:08    

mrBebert a écrit :

Tu peux faire en sorte de faire précéder chaque message par sa taille en octets (dans un entier).
Ainsi, tu lis d'abord l'entier (tu connais sa taille), puis les données (tu as leur taille) :)  
 
Ou alors, tu fais en sorte que tout les messages aient la même taille (mais ca risque de consommer inutilement de la bande passante :/ )


 
oui evidement mais bon je ne peux pas modifier le pgm serveur! Donc si je parviens q trouver ses sources, j'aurai peut etre une chance de connaitre les tailles.
Sinon y a pas d'autres moyens?
Je pense qu'il y a une fonction qui dit si il reste quelque chose dans la socket, je pourrai peut etre lire les octets un par un?  :heink:  
Cela dit je ne suis vraiment pas sur que mes problemes viennent de la.

Reply

Marsh Posté le 20-03-2003 à 20:17:08    

Tu peux aussi utiliser une socket non bloquante. Et tu boucles sur le recv() jusqu'à ce que tu ais reçu toutes les infos dont tu as besoin.

Reply

Marsh Posté le 20-03-2003 à 20:53:22    

mrBebert a écrit :

Tu peux aussi utiliser une socket non bloquante. Et tu boucles sur le recv() jusqu'à ce que tu ais reçu toutes les infos dont tu as besoin.


 
oui c'est ce que je voulais dire quand je disai lire les infos une par une.

Reply

Marsh Posté le 20-03-2003 à 22:00:54    

en udp t'aurais pas de pb avec un recv(s,buff,2048)
recv retournerai le nb d'octets qu'il a recu (<=2048)
 
maintenant, fo etre sur du protocol utilisé par ton server (tcp ou udp ?) ...

Reply

Marsh Posté le 20-03-2003 à 22:21:07    

Ca peut pas être des histoires de flush de buffer? Moi j'ai des problèmes étranges quand je transfert des fichiers... Ca marche un peu près bien, mais sur des gros fichiers, le fichiers produit contient aléatoirement des suites de 0.
Existe-t-il une fonction pour flusher des sockets? J'ai essayé fflush, mais sur un socket sous linux ca m'a fait des coredumps ;-/

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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