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

  FORUM HardWare.fr
  Programmation
  C++

  [ Quasi-Résolu ] [socket] Effectuer deux echanges sans deconnexion

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[ Quasi-Résolu ] [socket] Effectuer deux echanges sans deconnexion

n°1582858
kabal05
Posté le 05-07-2007 à 15:49:03  profilanswer
 

Bonjour à tous,
 
Je suis en train de développer un serveur en C++ en utilisant les sockets qui communique avec un client en J2ME (téléphone protable).
 
Lorsque j'effectue un seul échange de données (on appelera "échange" l'envoi d'une requete depuis le téléphone suivi de la réponse du serveur) suivi d'une deconnexion, tout se passe normalement.
 
Lorsque j'en effectue deux consécutifs sans deconnexion entre les deux, les données ne sont pas recues par le client. Elles sont pourtant annoncées comme "envoyées" par le serveur (la fonction send ne bloque pas).
 
Ces données semblent donc "en attente" dans un buffer quelconque et envoyées seulement lors de la deconnexion.
 
Existe-t-il une astuce pour effectuer deux échanges sans se déconnecter ?
 
Merci.


Message édité par kabal05 le 06-07-2007 à 11:46:49
mood
Publicité
Posté le 05-07-2007 à 15:49:03  profilanswer
 

n°1582898
_darkalt3_
Proctopathe
Posté le 05-07-2007 à 17:04:54  profilanswer
 

un flush ?
N'hésite pas à utiliser Ethereal pour voir ce qui se passe vraiment (genre t'as des concaténations de trames inattendues), et aussi à vérifier tout tes buffers au debugger.


---------------
Töp of the plöp
n°1582908
kabal05
Posté le 05-07-2007 à 17:12:36  profilanswer
 

_darkalt3_ a écrit :

un flush ?
N'hésite pas à utiliser Ethereal pour voir ce qui se passe vraiment (genre t'as des concaténations de trames inattendues), et aussi à vérifier tout tes buffers au debugger.


 
Dans le principe, c'est bien un flush que je veux faire mais je ne trouve pas de commande équivalente pour les sockets (j'ai oublié de préciser que j'utilisais winsock2.h).
 
Je vais voir ce que me donne ethereal.

n°1582914
_darkalt3_
Proctopathe
Posté le 05-07-2007 à 17:23:14  profilanswer
 

T'as aussi peut etre une option TCP_NODELAY qui envoie la trame direct;
sans ça, la socket attend d'etre pleine pour balancer la purée dans le reseau.


---------------
Töp of the plöp
n°1582920
kabal05
Posté le 05-07-2007 à 17:33:06  profilanswer
 

Oui effectivement, j'ai vu ca dans la doc et j'ai essayé :
 
erreur = setsockopt(ListeningSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&delay, sizeof(delay));
 
(ListeningSocket est ma socket et delay est un int que j'ai initialisé à 1)
 
Mais ca n'a rien changé. Soit je me suis trompé dans la facon de s'en servir (aucune erreur à l'execution, ca me renvoie 0) soit ca ne marche pas.

n°1582921
_darkalt3_
Proctopathe
Posté le 05-07-2007 à 17:34:00  profilanswer
 

A ton deuxieme envoi, le retour de send est 0 ?


---------------
Töp of the plöp
n°1582943
kabal05
Posté le 05-07-2007 à 17:55:47  profilanswer
 

En fait, je n'arrive pas jusqu'au deuxieme envoi. Je récapitule rapidement :
 
 1) J'envoi une requete depuis le client
 2) J'analyse la requete sur le serveur et je renvoie une donnée en conséquence
 3) je ferme tout
 
Ca, ca marche. Je recois la trame correcte sur le client.
Par contre :
 
 1) J'envoi une requete depuis le client
 2) J'analyse la requete sur le serveur et je renvoie une donnée en conséquence
 3) Le serveur me dit que la trame est envoyée (send me retourne la taille de ma trame)
 4) je ne quitte pas le serveur et j'attends une nouvelle requete du client
 5) le client ne recoit rien du tout ...
 
Si je fais un shutdown juste après l'envoi (coté serveur), je recois bien mes informations sur le client ("logique" ), mais je ne peux plus rien envoyer ("logique" aussi).
 
J'ai vraiment l'impression que la fonction send passe par un "buffer d'envoi" auquel je n'ai pas acces, et qu'elle vide ce buffer et l'envoi au client lors de la deconnexion de mon serveur...
 
Aucun message d'erreur sur le serveur, tout est normal pour lui. La fonction send me renvoie bien un code correct (longueur de trame envoyée correcte).

n°1583135
Taz
bisounours-codeur
Posté le 06-07-2007 à 11:25:56  profilanswer
 

(foutaise de TCP_NODELAY)
 
Je pense que tu as un problème ailleurs, le mode de fonctionnement que tu décris est tout à fait normal, tout le monde fait ça sans problème. Y a pas d'astuce. Ton client, il bloque sur son read ? tu ferais bien de stracer les deux, et de mettre un tcpdump au milieu. Ou alors si tu as du code juste pour voir ...

n°1583141
kabal05
Posté le 06-07-2007 à 11:33:42  profilanswer
 

J'ai résolu mon problème en envoyant à chaque fois un buffer de 1024 (char buffer[1024]) pour 100 octets maximum à envoyer, c'est pas la joie... Mais ca marche à chaque fois !!
 
La taille minimum du buffer à envoyer semble être de 800 ou un truc dans le style (mais je suis plus a 200 octets pres...).
 
Merci en tout cas pour vos réponses. Pour l'instant je m'en sors comme ca, on verra plus tard pour l'optimisation.

n°1583190
straffo
Posté le 06-07-2007 à 13:57:40  profilanswer
 

TCP ? UDP ?
 
Notre copain Nagle serait-il impliqué ?

mood
Publicité
Posté le 06-07-2007 à 13:57:40  profilanswer
 

n°1583191
kabal05
Posté le 06-07-2007 à 14:01:00  profilanswer
 

Je suis en TCP et j'ai bien l'impression que c'est cet enfoiré de Nagle qui m'a plombé pendant quelques jours :)

n°1583218
Taz
bisounours-codeur
Posté le 06-07-2007 à 14:53:01  profilanswer
 

y a pas de raison. 100 ou 1024, ça tient dans le même segment sur de l'ethernet. Nagle va attendre quelques ms avant d'envoyer. send envoie toujours sauf si on met l'option MSG_MORE, et c'est là que nagle entre en jeu. ce n'est pas nagle le problème.
 
t'as rien résolu du tout, j'attends toujours le strace/tcpdump/code etc

n°1583251
kabal05
Posté le 06-07-2007 à 15:38:03  profilanswer
 

Voici pour le code :  

Code :
  1. // Envoi
  2. void envoyer(SOCKET soc, char *envoi, bool *quit){
  3. int iStatus = 0;
  4. char buf[1024];
  5. strcpy(buf,envoi);
  6. iStatus = send(soc, (const char *)buf, sizeof(buf),0);
  7. cout << "Nb octets envoyes : " << iStatus << endl;
  8. if(iStatus == SOCKET_ERROR)
  9. {
  10.  cout << "send a echoue avec l'erreur : " << WSAGetLastError() << endl;
  11.  closesocket(soc);
  12.                 *quit = true;
  13. }
  14. }
  15. // Reception
  16. void recevoir(SOCKET soc, char *buffer, bool *quit){
  17. char recu[1024];
  18. int iStatus = 0;
  19. memset(recu,'\0',sizeof(recu));
  20. iStatus = recv(soc, recu, sizeof(recu), 0);
  21. if(iStatus == SOCKET_ERROR)
  22. {
  23.  cout << "recv a echoue avec l'erreur : " << WSAGetLastError() << endl;
  24.  closesocket(soc);
  25.  *quit = true;
  26. }
  27. else
  28. {
  29.  recu[iStatus] = '\0';
  30.  strcpy(buffer, recu);
  31. }
  32. }
  33. // Thread Client
  34. DWORD serveur::ClientThread(SOCKET soc){
  35. cout << "thread client demarre" << endl;
  36. char recu[1024];
  37. char envoi[1024];
  38. bool quit = false;
  39. bool REC = true;
  40. bool ENV = false;
  41. // Reception, Envoi et traitement
  42. while(!quit){
  43.  memset(recu,'\0',sizeof(recu));
  44.  memset(envoi,'\0',sizeof(envoi));
  45.  if(REC){
  46.   recevoir(soc, recu,&quit);
  47.   cout << "Recu du client : " << recu << endl;
  48.   traitement(&quit,&REC,&ENV,recu,envoi);
  49.  }
  50.  if(ENV){
  51.   envoyer(soc,envoi,&quit);
  52.   cout << "Envoye au client : " << envoi << endl;
  53.   ENV = false;
  54.   if(!quit)REC = true;
  55.  }
  56. }
  57. // FIN
  58. // FERMETURE DU SOCKET FILS
  59. if (shutdown(soc, SD_BOTH) == SOCKET_ERROR || closesocket(soc) == SOCKET_ERROR)
  60. {
  61.  cout << "La fermeture a echoue avec l'erreur : "<< WSAGetLastError() << endl;
  62.  return 103;
  63. }
  64. else
  65. {
  66.  cout << "Deconnexion du client." << endl;
  67. }
  68. // Libération du thread
  69. return 0;
  70. }


 
Le thread demarre après l'acceptation d'une connexion. Je vous fais grace de la fonction traitement, qui ne fait que manipuler des chaines et passer les booléens à true ou false (les enchainements d'envoi et de reception sont effectués correctement donc celle ci remplit son travail... De plus, lors des affichages cout << "Recu du client : " << recu << endl; et cout << "Envoye au client : " << envoi << endl; les chaines affichées sont correctes).


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

  [ Quasi-Résolu ] [socket] Effectuer deux echanges sans deconnexion

 

Sujets relatifs
[RESOLU]Problème de background avec des DIV[resolu]fonction qui modifie els paramètrs d'entrée
[JNI][résolu] chargement de librairies C++Problème affichage sous IE [RESOLU]
expression régulière [nouveau problème][Resolu]extraire un lecteur flv embedded
[RESOLU] [AS] du mal a démarrer[RÉSOLU] Aide pour une requete MySQL
JAVA - Client/Serveur sous Eclipse (RMI ou Socket ?)[RESOLU] Une liste de pays dans ma base de données SQL
Plus de sujets relatifs à : [ Quasi-Résolu ] [socket] Effectuer deux echanges sans deconnexion


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