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

  FORUM HardWare.fr
  Programmation
  C++

  problème de socket client --> bloquantes ou pas

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

problème de socket client --> bloquantes ou pas

n°612707
jagstang
Pa Capona ಠ_ಠ
Posté le 15-01-2004 à 16:20:14  profilanswer
 

Hello,
 
Voici le problème.  
 
Je travaille sur un client socket pour POP. Lorsque je send le message (par exemple "USER jagstang" )
 
je récupère tout de suite après la réponse avec recv()
 
Il arrive que le serveur ne soit pas assez prompt pour la réponse, et le buffer est vide...
 
J'ai pas trop l'envie de mettre des sleep ou autres...
 
J'ai lu pas mal de trucs à ce sujet, notamment l'utilisation de socket bloquantes / non bloquantes, ainsi que de faire un thread pour chaque envoi/réponse
 
Quelqu'un a-t-il une idée ?
 
Merci

mood
Publicité
Posté le 15-01-2004 à 16:20:14  profilanswer
 

n°612709
blackgodde​ss
vive le troll !
Posté le 15-01-2004 à 16:22:45  profilanswer
 

apparement si le buffer de recv est vide, c'est que ton socket n'est pas bloquant ou que la connexion a été coupée.
sinon, pour attendre l'arrivée de données, tu peux jouer avec select() de l'api socket


---------------
-( BlackGoddess )-
n°612770
jagstang
Pa Capona ಠ_ಠ
Posté le 15-01-2004 à 17:29:10  profilanswer
 

select ne change malheureusement rien....

n°612772
blackgodde​ss
vive le troll !
Posté le 15-01-2004 à 17:30:34  profilanswer
 

donne un bout de code pour voir ? du moment ou tu crée ton socket jusqu'au recv qui foire ?


---------------
-( BlackGoddess )-
n°612774
chrisbk
-
Posté le 15-01-2004 à 17:31:48  profilanswer
 

ben c pas bloquant par defaut ? comment se fesse que tu sois en non-bloquant ?

n°612808
xterminhat​e
Si vis pacem, para bellum.
Posté le 15-01-2004 à 18:25:54  profilanswer
 

Je t'invite à faire afficher la valeur retournée par recv() lorsque ce dernier se "débloque" sans retourner un seul octet de données.
 
En effet, recv() retourne 0 lorsque la connexion a été interrompue correctement independament de ta volonté. recv() retourne -1 (SOCKET_ERROR) lorsque la connexion a été interrompue de manière inatendue (genre "connection reset by peer" ).
 
Perso, j'ai un soucis du même genre avec un retour d'erreur égale à 183 (ca ne semble meme pas etre une erreur de type socket mais une erreur plus générale)... cela dit pas d'etonnement dans tous les cas, il y a visiblement bcp de raison pour qu'une connexion TCP se déconnecte toute seule ! :)
 
Cordialement,  
   Xter.

n°614378
jagstang
Pa Capona ಠ_ಠ
Posté le 17-01-2004 à 15:12:22  profilanswer
 

voilà.
 
création socket

Code :
  1. bool DahuSocks::Connect(const string &ip, const unsigned int port)
  2.     {
  3.     sin.sin_addr.s_addr = inet_addr(ip.c_str());
  4.     sin.sin_family  = AF_INET;
  5.     sin.sin_port  = htons(port);
  6.     sock = socket(AF_INET,SOCK_STREAM,0);
  7.     if (connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
  8.         isConnected = true ;
  9.     // socket option
  10.     int on = 1 ;
  11.     if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
  12.         isConnected = false;
  13.     /*int buffSize = BUFFERSIZE ;
  14.     if (setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (const char *) &buffSize, sizeof (buffSize) ) == -1 )
  15.         isConnected = false;
  16.     */
  17.     // bind
  18.     //if (bind(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
  19.     //    cout << "erreur bind" ;
  20.     // maximum time to wait
  21.     fd_set a ;
  22.     a.fd_array[0] = sock ;
  23.     a.fd_count = 1 ;
  24.     timeval b ;
  25.     b.tv_sec = 2 ;
  26.     b.tv_usec = 200 ;
  27.     select(0, &a, &a, &a, &b) ;
  28.     // socket non bloquante
  29.     /*u_long argp=1;
  30.     ioctlsocket(sock, FIONBIO, &argp) ;
  31.     if (argp == 0)
  32.       return false ;
  33.     */
  34.     return isConnected ;
  35.     }[code]
  36. string DahuSocks::Recv(bool multiline)
  37.     {
  38.     char mbuffer [BUFFERSIZE+1] ;
  39.     string sbuffer="" ;
  40.     int errcode=0 ;
  41.     int i=0 ;
  42.     long downloaded=0 ;
  43.     char bspace[] = {8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0 } ;
  44.     char wait[] = {'|', '/', '-', '\\'} ;
  45.     do
  46.         {
  47.         WSASetLastError(0) ;
  48.         memset(mbuffer, 0, BUFFERSIZE) ;
  49.         errcode = recv(sock, mbuffer, BUFFERSIZE, 0) ;
  50.         sbuffer.append(mbuffer) ;
  51.         #ifdef DEBUG
  52.         //cout << "\nWSA :" << WSAGetLastError() ;
  53.         //cout << "\nerrcode : " << errcode ;
  54.         #endif
  55.         downloaded += errcode ;
  56.         if (i++>0)
  57.             cout << bspace << wait[i%4] << " " << downloaded << " bytes" ;
  58.         }
  59.     while (errcode == BUFFERSIZE && WSAGetLastError()==0) ;
  60.     if (i>1)
  61.         {
  62.         cout << bspace ;
  63.         cout << downloaded << " bytes OK" ;
  64.         }
  65.     return sbuffer ;
  66.     }


 
le problèmest est que parfois le buffer n'est pas plein. Donc la boucle s'arrête est le message est tronqué
 
Je précise que j'utilise ceci pour récupérer un mail sur un serveur POP.


Message édité par jagstang le 17-01-2004 à 15:23:36
n°614380
jagstang
Pa Capona ಠ_ಠ
Posté le 17-01-2004 à 15:15:42  profilanswer
 

Je comprends pas le problèmes, Sous linux sans ces WSA ça fonctionne très bien. Mais l'adaptation sous Windows est plus difficile que je pensais.


Message édité par jagstang le 18-01-2004 à 01:06:46
n°614934
jagstang
Pa Capona ಠ_ಠ
Posté le 18-01-2004 à 18:34:55  profilanswer
 

:bounce:  :cry:

n°617046
xterminhat​e
Si vis pacem, para bellum.
Posté le 20-01-2004 à 21:10:31  profilanswer
 

Franchement, il n'a vraiment pas l'air assez robuste ton code, vis a vis des exceptions (ie.: en cas d'erreur de retour de l'appel recv() en particulier).
 
Courage,
   Xter.

mood
Publicité
Posté le 20-01-2004 à 21:10:31  profilanswer
 

n°617050
jagstang
Pa Capona ಠ_ಠ
Posté le 20-01-2004 à 21:15:32  profilanswer
 

lol. j'ai bien remarqué merci. Mais avant de gérer les exceptions, j'aimerai bien que ça fonctionne dans une utilisation normale...
 
Sinon, t'as pas une idée ?

n°617681
xterminhat​e
Si vis pacem, para bellum.
Posté le 21-01-2004 à 12:35:43  profilanswer
 

Remplace

Code :
  1. while (errcode == BUFFERSIZE && WSAGetLastError()==0) ;


par

Code :
  1. while( errcode > 0 );


 
 
Et compile ton code en definissant ton preprocesseur DEBUG et ajoute un max de messages pour superviser l'etat des variables. Puis post les messages de debug ici.
 
Cordialement,
   Xter.


Message édité par xterminhate le 21-01-2004 à 23:27:15
n°617728
jagstang
Pa Capona ಠ_ಠ
Posté le 21-01-2004 à 13:05:48  profilanswer
 

je ne peux pas faire errcode > 0. Car comme les sockets étant bloquantes, un recv de trop me bloque l'application (qui attend...)
 
Merci pour ton aide en tout cas

n°618512
xterminhat​e
Si vis pacem, para bellum.
Posté le 21-01-2004 à 23:26:12  profilanswer
 

Pffff... tu as essayé au moins ?


Message édité par xterminhate le 21-01-2004 à 23:28:02
n°618536
jagstang
Pa Capona ಠ_ಠ
Posté le 21-01-2004 à 23:40:19  profilanswer
 

Oui merci j'ai essayé bien avant de poster sur ce forum...

n°619379
xterminhat​e
Si vis pacem, para bellum.
Posté le 22-01-2004 à 20:32:58  profilanswer
 

Tu devrais adopter une gestion de socket plus avancée avec un appel selec() avant recv() et close().
 
Cordialement,
   Xter.

n°620286
jagstang
Pa Capona ಠ_ಠ
Posté le 23-01-2004 à 15:21:40  profilanswer
 

dans quel but ? le problème vient-il de là ?
 
Excuse-moi mais gestion de socket plus avancée techniquement ça m'aide pas beaucoup...

n°620488
blackgodde​ss
vive le troll !
Posté le 23-01-2004 à 18:00:25  profilanswer
 

un petit exemple :
 

Code :
  1. std::string receive (const timeval* timeout, SOCKET & s) // ou const SOCKET & s, je suis plus sûr du prototype des API utilisées)
  2. {
  3.   fd_set fds;
  4.   FD_ZERO(&fds);
  5.   FD_SET(s, &fds);
  6.   unsigned long cbdata;
  7.   int cbopt = sizeof(cbdata);
  8.   if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char*>(&cbdata), &cbopt) == SOCKET_ERROR /* -1 */) { /* erreur */ }
  9.   char* data = new char[cbdata];
  10.   std::string ret; 
  11.   int select_ret; 
  12.   while((select_ret = select(0, &fds, NULL, NULL, timeout)) > 0))
  13.   {
  14.     if(FD_ISSET(s, &fds))
  15.     {
  16.       int len = recv(s, data, cbdata, 0);
  17.       if(len == SOCKET_ERROR /* -1 */) { /* erreur */ }
  18.       ret.append(std::string(data, len));
  19.     }
  20.   }
  21.   delete[] data; 
  22.   if(select_ret == SOCKET_ERROR) // -1 sous *nix
  23.   {
  24.     // il y a eu une erreur
  25.   } else {
  26.     // tout s'est déroulé correctement
  27.   }
  28.   return ret;
  29. }


 
c'est un peu codé "à la gros porc" c'est juste pour te donner une idée : le but ici est d'attendre et de recevoir jusqu'à ce que le serveur n'envoit plus rien pendant le temps 'timeout'.


Message édité par blackgoddess le 23-01-2004 à 18:03:00

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

  problème de socket client --> bloquantes ou pas

 

Sujets relatifs
Problème de "!" dans un mail envoyé en php[java swing] probleme de taille avec un JTextField
[XML/XSL]génération d'un XML a partir d'un XML par XSL problemeProblème install VirtualTreeView
Socket standard win32/unix avec Borland c++ builder 6Probleme de Charset sous Windows et pas sous Unix
url rewriting --> problème (avec mon serveur).Probleme avec la fct bcdiv()
[Sql] Problème sur croisement de tablesProblême de concept - Comment gerer des catégories ?
Plus de sujets relatifs à : problème de socket client --> bloquantes ou pas


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