[ eVC++ ] [socket] Eviter les envois de données "dans la nature"

Eviter les envois de données "dans la nature" [ eVC++ ] [socket] - C++ - Programmation

Marsh Posté le 17-11-2005 à 12:28:22    

Bonjour,
 
je suis actuellement en train de retoucher un programme pour PocketPC (PPC).
Nous rencontrons des pertes de connexion régulières (ca passe par wifi).
Ca se traduit par un lag infini et le PPC est bloqué (socket synchrone, attend une réponse du serveur).
On reboot alors le PPC mais le serveur lui reste a l'état "connecté".
Il faut donc également repasser le serveur en mode "écoute".
 
Pour éviter les désagréments de l'utilisateur, j'essaye d'automatiser la reconnexion sur le PPC.
(je ne parle pas du serveur, admettons qu'il soit en écoute dès que la connexion avec le PPC est perdue).
 
 
Voici le code du PPC pour envoyer un message au serveur (requête sql).
Comme je fonctionne avec des sockets synchrones, chaque message envoyé attends une réponse du serveur
 

Code :
  1. bool connexion::send_msg(CString MSG)
  2. {
  3. if((snd_msg(MSG))==false) //envoi du MSG
  4. {
  5.  MessageBox(NULL,TEXT("Erreur à l'envoi. Pointez OK pour vous reconnecter" ),TEXT("Erreur" ),MB_OK);
  6.  //si la reconnexion est un succès on réenvoie le message
  7.  if (reconnect()==true)
  8.  {
  9.   send_msg(MSG);
  10.   return true;
  11.  }
  12.  else
  13.  {
  14.   MessageBox(NULL,TEXT("La reconnexion a echoué, contactez le service informatique !" ),TEXT("Erreur" ),MB_OK);
  15.   return false;
  16.  }
  17. }
  18. if((rcv_msg())==false) //réception des données/remplissage du recordset
  19. {
  20.  MessageBox(NULL,TEXT("Erreur à la reception. Pointez OK pour vous reconnecter" ),TEXT("Erreur" ),MB_OK);
  21.  //si la reconnexion est un succès on réenvoie le message
  22.  if (reconnect()==true)
  23.  {
  24.   send_msg(MSG);
  25.   return true;
  26.  }
  27.  else
  28.  {
  29.   MessageBox(NULL,TEXT("La reconnexion a echoué, contactez le service informatique !" ),TEXT("Erreur" ),MB_OK);
  30.   return false;
  31.  }
  32. }
  33. return true;
  34. }


 
Si l'envoi de mon message échoue, je lance la reconnexion puis je réenvoie le message.
Si la réception de la réponse échoue, je lance la reconnexion puis je réenvoie le message.
 
Dans ce dernier cas, je prend donc le risque d'envoyer deux fois le même message pour obtenir une seule réponse et donc foutre en l'air ma base de données derrière.
 
Par exemple :  
envoi de : insert bidule into machin --> l'envoi a été effectué
reception : erreur
reconnexion
envoi de : insert bidule into machin --> l'envoi a été effectué
reception : ecriture ok --> la reception a été effectuée
 
Et là on peux se poser deux questions par rapport à l'erreur obtenue à la 1ère réception:
- l'envoi de données est-il parvenu jusque au serveur ? (est-on connecté au serveur ?)
- le serveur a-t-il renvoyé un accusé ? (le serveur s'est-il planté en cours de route ?)
 
J'ai donc peut être inseré deux fois la valeur bidule dans ma table parceque mon premier accusé n'est pas arrivé à destination mais que la requete a bien été executée.
 
Voici un boût de code pour mes envois de message

Code :
  1. bool connexion::snd_msg(CString MSG)
  2. {
  3. int SIZE=10000;
  4. int test;
  5. //conversion de la CString MSG en char*
  6. char* strTo= (char*)malloc(SIZE);
  7. //MSG = MSG + " limit 10"; //limite à dix réponses (10 enregistrements retournés max)
  8. wcstombs(strTo,MSG ,SIZE);
  9. // Send a string to the server.
  10. switch (send (ServerSock, strTo , strlen (strTo) + 1, 0))
  11. {
  12.  case SOCKET_ERROR:
  13.  {
  14.    free(strTo);
  15.    return false;
  16.  }break;
  17.  case 0 :
  18.  {
  19.   free(strTo);
  20.   return false;
  21.  }break;
  22.  default :
  23.  {
  24.   free(strTo);
  25.   return true;
  26.  }break;
  27. }
  28. }


 
et ici la reception
 

Code :
  1. bool connexion::rcv_msg()
  2. {
  3. int SIZE=10000;
  4. char* bytes= (char*)malloc(SIZE);
  5. switch (recv(ServerSock, bytes, SIZE,0))
  6. {
  7.  case SOCKET_ERROR:
  8.  {
  9.    free(bytes);
  10.    return false;
  11.  }break;
  12.  case 0:
  13.  {
  14.   free(bytes);
  15.   return false;
  16.  }break;
  17.  default:
  18.  {
  19.   if ((decoupage_ligne(bytes,SIZE))==false)
  20.   {
  21.    //traitement impossible
  22.    free(bytes);
  23.    return false;
  24.   }
  25.   free(bytes);
  26.   return true;
  27.  }break;
  28. }


 
En lisant la doc, on sais que si recv renvoie 0, la connexion n'est plus disponible, je l'ai testé (en fermant le serveur) et ca fonctionne.
par contre pour send (avec le serveur fermé), la valeur 0 n'est jamais renvoyée (normal c'est ps dans la doc) et SOCKET_ERROR n'est JAMAIS retourné !
Donc j'envoie des données qui n'arrivent jamais et je n'en suis pas informé ...
 

Citation :

If no error occurs, send returns the total number of bytes sent, which can be less than the number indicated by len. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.


 

Citation :

If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.


 
Une idée ? :'(


Message édité par jeoff le 17-11-2005 à 12:32:56
Reply

Marsh Posté le 17-11-2005 à 12:28:22   

Reply

Sujets relatifs:

Leave a Replay

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