[Socket Linux] Qd le client ferme, le serveur boucle sur le message

Qd le client ferme, le serveur boucle sur le message [Socket Linux] - C++ - Programmation

Marsh Posté le 28-04-2003 à 10:46:55    

Je dois faire un chat sous linux en C et avec ncurses, jusque là, ca va a peu près, mais un de mes problèmes, c'est que lorsque je ferme le client, le serveur boucle sur la reception du dernier message recu et me l'affiche 500 fois par seconde!!  
 
Comment faire pour détecter la fermeture de la socket ?
 
En fait, au niveau du serveur, je fait une boucle qui se met en pause avec un "select" pour attendre une opération de lecture sur la socket, et ensuite, il passe à un "recv" pour lire ce qui est a lire.
 
Mais qd le client ferme, le select réussi immédiatement et recv me renvoie le dernier message qu'il a recu.
Je pensais que recv renverrai une erreur disant que la socket avait fermée mais il n'en est rien.
 
Merci !
 
PS : je suis sous debian (knoppix v3.1)

Reply

Marsh Posté le 28-04-2003 à 10:46:55   

Reply

Marsh Posté le 28-04-2003 à 10:58:44    

Une solution pourrait être d'établir un protocole de communication entre ton client et ton serveur, non?
Comme ca avant de fermer le client envoie un message spécifique disant "attention je m'en vais", ce qui te permet de fermer au niveau serveur...
Je sais pas si c'est ce que tu veux - sinon ce serait bien que tu donnes la portion de code correspondant à tout ça, histoire qu'on voie si une solution différente est utilisable...

Reply

Marsh Posté le 28-04-2003 à 11:02:12    

Je sais, c'est exactement ce que je suis en train de mettre dans mon code, mais je me dis qu'il doit y avoir une autre solution, sinon un plantage d'un des clients, sans qu'il ai pu envoyer le message de deconnexion ferai planter le serveur.
 
Et vu qu'aucun des serveurs qu'on utilise tous les jours plante si on reboote nos PC, c'est qu'il y a une detection au niveau du serveur...
Merci quand même, je vais continuer dans cette voie de toute façon. Je posterai la partie de mon code dans pas longtemps, le temps d'acceder au serveur.

Reply

Marsh Posté le 28-04-2003 à 11:11:42    

la taille du message recu par le socket (quand la liaison morte) n'est elle pas egale a 0 ?  
 
;)


---------------
Signatures aux choix Votez:  O - Le python c'est bon, mangez-en  O - L'abus de forum rend dependant, postez avec modération
Reply

Marsh Posté le 28-04-2003 à 11:22:59    

Justement, c'est ça le genre de trucs auquels je me serai attendu, mais cet enfoiré me renvoie indéfiniment le dernier message qu'il a intercepte : genre le client dit "Bonjour" , si le client ferme après; le serveur va recevoir 3000 fois "Bonjour"

Reply

Marsh Posté le 28-04-2003 à 11:29:18    

Larry99 a écrit :

Justement, c'est ça le genre de trucs auquels je me serai attendu, mais cet enfoiré me renvoie indéfiniment le dernier message qu'il a intercepte : genre le client dit "Bonjour" , si le client ferme après; le serveur va recevoir 3000 fois "Bonjour"
 


et la valeur de retour du select?
Tu as pas un truc genre -1 quand ca ne marche pas?

Reply

Marsh Posté le 28-04-2003 à 11:55:42    

j'ai une appli serveur linux, en voici un extrait :  
 

Code :
  1. if((lg = Recvn (data,tailledata)) == -1) //recoi les data ( Recvn fonctionne comme la fonction recv )
  2.          {
  3.             perror("Adapte.Recvn.recv " );
  4.             continue;
  5.          }
  6. [...]
  7.       if(lg==0)
  8.       {
  9.          printf("%-5i Adapte >\nMessage vide recu : La connexion socket a ete perdue.\n",getpid());
  10.          break;
  11.       }


 
j'espere que ca t'aidera ;)


Message édité par Phod le 28-04-2003 à 13:35:42

---------------
Signatures aux choix Votez:  O - Le python c'est bon, mangez-en  O - L'abus de forum rend dependant, postez avec modération
Reply

Marsh Posté le 28-04-2003 à 13:02:46    

hum, c plutot étrange cette histoire...
 
recv doit forcement renvoyer 0 à un moment donné
 
si tu envoies "bonjour" depuis ton client, puis ensuite si tu envoies "salut" depuis le meme client, recois-tu le "salut" sur le server (après avoir bien recu le "bonjour"?
 

Reply

Marsh Posté le 28-04-2003 à 14:07:50    

Ben ouais, justement, je peux envoyer plein de trucs, ils sont tous bien reçus, mais quand je ferme le client, j'ai ce truc qui me gène. Sinon, tout se passe comme ça devrai.
 
En fait, j'en viens à me demander si c'est pas mon linux qui merde, mais à ma fac, le problème est différent, quand je ferme un client, ça me plante direct le serveur dans la moitié des cas et dans l'autre moitié, ça me fait comme chez moi.
 
Select renvoie pas -1 non plus..

Reply

Marsh Posté le 28-04-2003 à 14:16:56    

Oui mais est ce que select ne renvoie pas 0 plustot ?

Reply

Marsh Posté le 28-04-2003 à 14:16:56   

Reply

Marsh Posté le 28-04-2003 à 15:18:13    

Larry99> a tu testé comme je le fait dans mon bout de code le retour de recv() ?  :??:  
 
paske au moment de mettre au point ce serveur j'ai eu le meme pb que toi... et j'ai vu que si le client etait fermé violement, recv se debloquait en indicant 0 octets lu. par contre le buffer qu'on lui a passé en parametre n'etait pas vidé (c donc le dernier msg se repete indefiniment)


---------------
Signatures aux choix Votez:  O - Le python c'est bon, mangez-en  O - L'abus de forum rend dependant, postez avec modération
Reply

Marsh Posté le 28-04-2003 à 16:08:52    

c'est clair, il faut absolument tester si tu detectes un recv retournant 0 pour enlever ton socket du fd_set
 
ce qui m'étonne c'est qu'il semble que ca n'arrive jamais !
il nous manque des infos, la ... ya forcement un bug qq part.
 
t'as pas un bout de code?

Reply

Marsh Posté le 28-04-2003 à 22:51:54    

http://progfr.tuxfamily.org/index. [...] ble=struct
 
et tu telecharge le tutorial sur les socket.
 
il marche bien .
 
g fé un while(1)
{
recv(...);
...
et il s arrete kan le client se deconnect

Reply

Marsh Posté le 29-04-2003 à 08:45:48    

Code :
  1. while(1)
  2. {
  3.   fd_set lecture;
  4.   FD_ZERO(&lecture);
  5.   FD_SET(client,&lecture);
  6.   int max=client+1;
  7.   select(max,&lecture,NULL,NULL,NULL);
  8.   // l'appel a select a reussi, il y a des donnees a recevoir du client.
  9.   void *buf=(void*) malloc(sizeof(Msg));
  10.   recv(client,buf,sizeof(Msg),MSG_WAITALL);
  11.   // On transfere le buffer ailleur en le recopiant..
  12.   free(buf);
  13. }

 
 
C'est a peu près ce que je fais, sauf que là, effectivement ya pas de vérif du nombre d'octets recus.. Et je me rappelle plus si je l'ai fait cette vérif avant et si ça renvoyai pas qq chose de positif.
Je peux pas recompiler mon prog pour l'instant pour tester car j'ai un problème de compilo à ma fac.
 
D'ailleur, si quelqu'un peu me dire pourquoi ce bout de code ne marche pas à ma fac;  
parce que moi je m'arrache les cheveux.

Code :
  1. #include <stdio.h>
  2. int main(int argc,char *argv[])
  3. {
  4.   char Message[]="coucou";
  5.   printf(Message);
  6.   int i=3;
  7.   printf("i= %d", i);
  8.   return 0;
  9. }

 
 
Ce bout de code me renvoie :  
 
toto.c: In function `main':
toto.c:7: parse error before `int'
toto.c:8: `i' undeclared (first use in this function)
toto.c:8: (Each undeclared identifier is reported only once
toto.c:8: for each function it appears in.)
 
Merci beaucoup pour votre aide en attendant, je vais teste le retour de recv dès que je peux.

Reply

Marsh Posté le 29-04-2003 à 08:50:54    

Larry99 a écrit :

D'ailleur, si quelqu'un peu me dire pourquoi ce bout de code ne marche pas à ma fac;  
parce que moi je m'arrache les cheveux.

Code :
  1. #include <stdio.h>
  2. int main(int argc,char *argv[])
  3. {
  4.   char Message[]="coucou";
  5.   printf(Message);
  6.   int i=3;
  7.   printf("i= %d", i);
  8.   return 0;
  9. }

 
 
Ce bout de code me renvoie :  
 
toto.c: In function `main':
toto.c:7: parse error before `int'
toto.c:8: `i' undeclared (first use in this function)
toto.c:8: (Each undeclared identifier is reported only once
toto.c:8: for each function it appears in.)
 
Merci beaucoup pour votre aide en attendant, je vais teste le retour de recv dès que je peux.


Le C n'accepte pas les déclarations au mileu de la fonction...ton i doit être déclaré au début.
Je vois que ça...


Message édité par skeye le 29-04-2003 à 08:51:11
Reply

Marsh Posté le 29-04-2003 à 08:54:52    

D'ailleurs ca compile chez moi ce truc...c'est pas normal ca!
gcc doit prendre ca pour du C++... :??:

Reply

Marsh Posté le 29-04-2003 à 14:47:36    

Bon, ça marche pour le 0 de retour de recv, merci ! Je m'en étais pas préoccupé en pensant que ca renverrai une erreur à la place.
 
En ce qui concerne la compilation qui foire, je faisais surtout du C++ et je savais pas qu'en C il fallait définir toutes les variables au début (je pensais que ct juste pr le pascal/delphi).
Mais c'est bizarre, parce que à part à la fac, ça marche chez moi, même en spécifiant gcc -x c , pour lui demander de considérer que le code est en C pur.
Donc ça vient ptet de ma fac et de leur compilo qui est une mauvaise version de gcc...  ??
 
En tout cas, merci pour votre aide à tous et votre rapidité !

Reply

Marsh Posté le 29-04-2003 à 15:13:24    

skeye a *crit :

D'ailleurs ca compile chez moi ce truc...c'est pas normal ca!
gcc doit prendre ca pour du C++... :??:  


 
Il me semble que en C99 c'est autorise.

Reply

Marsh Posté le 29-04-2003 à 21:05:44    

si la connection est fermé par le client ton recv retourne 0 chez le serveur

Reply

Sujets relatifs:

Leave a Replay

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