Socket, problème à l'écriture.

Socket, problème à l'écriture. - C - Programmation

Marsh Posté le 01-10-2006 à 15:17:13    

Bonjour,
 
Sous Linux, J'ai écris un programme C qui utilise les sockets tcp/ip.
c'est un programme client qui se connecte sur un serveur.
 
La communication fonctionne trés bien entre le client et le serveur.
Le seul pb est que le serveur coupe la connexion aprés un time-out.
 
Si mon programme est en dehors de ce timeout, il quitte dés la fonction send() sans message d'erreur.
 
Extrait:
 

Code :
  1. if ( send(device, rxbuff, nb1 + 4 + 1, 0) < 0)
  2. {
  3.  perror("Emission sur socket: " );
  4.  return 2;
  5. }


 
Mon programme est sensé tourné en continu avec la connexion toujours active.
Je ne sais pas gérer ces déconnexions, je pensais que la fonction send() me retournerais un code < 0 mais ce n'est pas le cas.
Aucune erreur renvoyée ni par le programme ni sur la console du programme.
 
Votre avis ?
 
merci

Reply

Marsh Posté le 01-10-2006 à 15:17:13   

Reply

Marsh Posté le 01-10-2006 à 17:27:05    

domos a écrit :

Bonjour,
 
Sous Linux, J'ai écris un programme C qui utilise les sockets tcp/ip.
c'est un programme client qui se connecte sur un serveur.
 
La communication fonctionne trés bien entre le client et le serveur.
Le seul pb est que le serveur coupe la connexion aprés un time-out.
 
Si mon programme est en dehors de ce timeout, il quitte dés la fonction send() sans message d'erreur.
 
Extrait:
 

Code :
  1. if ( send(device, rxbuff, nb1 + 4 + 1, 0) < 0)
  2. {
  3.  perror("Emission sur socket: " );
  4.  return 2;
  5. }


 
Mon programme est sensé tourné en continu avec la connexion toujours active.
Je ne sais pas gérer ces déconnexions, je pensais que la fonction send() me retournerais un code < 0 mais ce n'est pas le cas.
Aucune erreur renvoyée ni par le programme ni sur la console du programme.
 
Votre avis ?
 
merci


Notre avis c'est que cela ne vient pas de "send" (sauf si rxbuff n'est pas de type "pointeur" ).
Peut-être faudrait le code complet de ton client...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 01-10-2006 à 19:05:25    

et les autres retour de send, tu t'en fiches ?

Reply

Marsh Posté le 01-10-2006 à 23:47:40    

Sve@r a écrit :

Notre avis c'est que cela ne vient pas de "send" (sauf si rxbuff n'est pas de type "pointeur" ).
Peut-être faudrait le code complet de ton client...


 
 
Effectivement rxbuff n'est de type pointeur.
Voici la routine appelée.
j'envoie une trame de type i2c sur le socket et j'entend une réponse.
Je précise que je ne maitrise pas le C et que j'ai repris des exemples donnés.
 
Cette routine fonctionne bien sauf dans le cas ou la com est coupée.
 

Code :
  1. /* ---------------------------------------------------------------------------- */
  2. int i2c_write(int device, unsigned char cardadr, unsigned char i2cadr, unsigned char nb, unsigned char *buf)
  3. {
  4. // Init. timeout pour select.
  5. timeout.tv_sec = 5;  // TimeOut à 5 secondes.
  6. timeout.tv_usec = 0;
  7. int result;
  8. int res ;
  9. unsigned char txbuff[255] ;
  10. unsigned char rxbuff[255] ;
  11. txbuff[0] = ENTETE ;
  12. txbuff[1] = cardadr ;
  13. txbuff[2] = i2cadr & 0xFE ;  // Force bit 0 (R/W) à 0 pour indiquer une écriture.
  14. txbuff[3] = nb ;
  15. txbuff[4] = '\0' ;
  16. buf[nb]   = '\0' ;
  17. strcat(txbuff, buf) ;
  18. // Envoi de la chaine par le socket ouvert.
  19. printf("-- Ecriture socket W I2C\n" ) ;
  20. if ( send(device, txbuff, nb + 4, 0) < 0 )
  21. {
  22.  perror("Emission sur socket: " );
  23.  syslog(LOG_ERR, "Erreur à l'emission sur l'interface rs232-i2c [%02X] à l'écriture i2c !", cardadr);
  24.  return 2;
  25. }
  26. // Attend pendant TimeOut une réception sur le socket.
  27. printf("-- Select socket\n" ) ;
  28. result = select(device+1, &readfds, NULL, NULL, &timeout) ;
  29. printf("-- Retour Select socket: %d\n", result) ;
  30. switch(result)
  31. {
  32.  case 0:
  33.   //printf("Timeout attente réception à l'écriture i2c !\n" );
  34.   syslog(LOG_ERR, "Erreur pas de réponse de l'interface rs232-i2c [%02X] à l'écriture i2c !", cardadr);
  35.   return 2;
  36.  case -1:
  37.   perror("Select socket: " );
  38.   syslog(LOG_ERR, "Erreur SELECT l'interface rs232-i2c [%02X] à l'écriture i2c !", cardadr);
  39.   return 2;
  40.  default:
  41.   if (FD_ISSET(device, &readfds))
  42.   {
  43.    // Lecture du socket (1 caratère).
  44.    printf("-- Lecture socket\n" ) ;
  45.    res = recv(device, rxbuff, 1, 0);
  46.    if(res < 0)
  47.    {
  48.     perror("Réception socket: " );
  49.     syslog(LOG_ERR, "Erreur à la réception de l'interface rs232-i2c [%02X] à l'écriture i2c !", cardadr);
  50.     return 2;
  51.    }
  52.    //printf("-- ACK à l'écriture i2c: %02x\n", rxbuff[0]) ;
  53.   }
  54.   else
  55.   {
  56.    //printf("Not FD_ISSET\n" ) ; // Pas utile.
  57.    syslog(LOG_ERR, "Erreur FD_ISSET de l'interface rs232-i2c [%02X] à l'écriture i2c !", cardadr);
  58.    return 2;
  59.   }
  60. }
  61. return rxbuff[0] ;
  62. }


 
j'ai rajouté des "printf" pour suivre le programme et il s'arréte bien au 'send' puisque je n'ai pas la suite.
Et pour répondre à la remarque concernant "les autres retour de send", comment les vérifier puisque send semble planté.
 
J'ai testé en mettant txbuuf/rxbuff en pointeur mais cela ne marche plus du tout.
 
Merci de ne pas taper sur la tête  :pt1cable:

Reply

Marsh Posté le 02-10-2006 à 09:44:53    

send qui plante, mais bien sur ...
 
send(device, txbuff, nb + 4
 
 
t'es sur que c'est pas tout simplement 5 ?

Reply

Marsh Posté le 02-10-2006 à 11:38:33    

Taz a écrit :

send qui plante, mais bien sur ...
 
send(device, txbuff, nb + 4
 
 
t'es sur que c'est pas tout simplement 5 ?


 
Non, puisqu'il j'envoie 4 octets en entete plus les nb se trouvant dans  buf.
 

Code :
  1. #
  2.     txbuff[0] = ENTETE ;
  3.     txbuff[1] = cardadr ;
  4.     txbuff[2] = i2cadr & 0xFE ;        // Force bit 0 (R/W) à 0 pour indiquer une écriture.
  5.     txbuff[3] = nb ;                       // nb = nombre octets de buf
  6. ...
  7.     strcat(txbuff, buf) ;


 
Cela fonctionne trés bien sauf quand le hosts a coupé la connexion.


Message édité par domos le 02-10-2006 à 12:25:16
Reply

Marsh Posté le 02-10-2006 à 12:51:34    

t'es sur que txbuff est assez grand (à priori non dans certains cas). bon tu regardes le retour de send et c'est tout. ça veut dire quoi 'send plante' ...

Reply

Marsh Posté le 02-10-2006 à 13:28:17    

Taz a écrit :

t'es sur que txbuff est assez grand (à priori non dans certains cas). bon tu regardes le retour de send et c'est tout. ça veut dire quoi 'send plante' ...


 
txbuff est largement dimensionné car il n'y qu'une dizaine d'octets en moyenne.
J'aimerais bien regarder le retour de send, le pb, c'est qu''il n'y a pas de retour.
Le "printf" juste avant le "send" s'affiche aprés le programme quitte sans avertissement,  
ni d'"erreur de segmentation".

Reply

Marsh Posté le 02-10-2006 à 14:50:11    

et ben tu sors ton débugger.

Reply

Marsh Posté le 02-10-2006 à 23:30:28    

Taz a écrit :

et ben tu sors ton débugger.


 
Le pb était bien celui indiqué par Sve@r, il faut bien que txbuff soit un pointeur.
Il n'y a plus de plantage lorsque la connexion est coupée.
 
J'avais déjà testé avec des pointeurs mais cela ne fonctionnait pas car je ne savais pas initialiser une chaine pointeur à ce moment là.
 
merci pour votre aide

Reply

Marsh Posté le 02-10-2006 à 23:30:28   

Reply

Marsh Posté le 03-10-2006 à 09:31:56    

quoi un pointeur ? c'est quoi cette histoire ? tu sais plus comment fonctionne un tableau ou quoi ?

Reply

Marsh Posté le 03-10-2006 à 12:36:13    

Taz a écrit :

quoi un pointeur ? c'est quoi cette histoire ? tu sais plus comment fonctionne un tableau ou quoi ?


 
Restons calme, je rappel que je ne suis pas un spécialiste du C.
 
int send(int s, const void *msg, size_t len, int flags);  
 
D'aprés mes lectures, il y a quand même une difference entre une variable chaine et un pointeur sur une chaine.
 
En tout cas, 'send' ne plante plus en déclarant un txbuff comme pointeur .

Reply

Marsh Posté le 03-10-2006 à 12:59:03    

domos a écrit :

En tout cas, 'send' ne plante plus en déclarant un txbuff comme pointeur .


A condition, bien sûr, que ce pointeur soit correctement initialisé.


Message édité par Emmanuel Delahaye le 03-10-2006 à 13:00:53

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 03-10-2006 à 20:51:09    

domos a écrit :


D'aprés mes lectures, il y a quand même une difference entre une variable chaine et un pointeur sur une chaine.

Oui mais tu es désespérant; Quand tu lis une chose, lis le jusqu'au bout et laisse tomber le mysticisme. Si tu as 't' est tableau de 'n' éléments de type 'T', alors 't' est implicitement convertible en 'T*const' pointant sur le son premier élément.
 
Mais tu nous dis que send est surchargé pour prendre soit un tableau soit un pointeur en argument, je laisse tomber.
 
Bref, le problème n'est pas là, mais alors pas du tout.
 
T'as qu'à faire
 
char buf[100];
char *p = buf;
send(..., buf, ...);
 
si t'es pas convaincu ...

Reply

Marsh Posté le 03-10-2006 à 22:33:48    

domos a écrit :

Le pb était bien celui indiqué par Sve@r, il faut bien que txbuff soit un pointeur.


Pfff... J'avais failli ne pas le dire tellement cela me paraissait évident. C'est comme si j'avais dit que "nbl" devait être un entier ou "device" un descripteur valide...
 

Taz a écrit :

T'as qu'à faire
 
char buf[100];
char *p = buf;
send(..., buf, ...);
 
si t'es pas convaincu ...


Tu veux sans doute dire "send(..., p, ...)" sinon je vois pas pourquoi tu inclus ce "p" dans l'histoire...


Message édité par Sve@r le 03-10-2006 à 22:37:53

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 03-10-2006 à 22:37:03    

vi, enfin c'est pareil justement :o

Reply

Marsh Posté le 03-10-2006 à 22:49:06    

mais pour conclure ce thread, je dirais juste : envoie en même ce que tu veux envoyer en même temps. Aggréger les messages pour faire un seul send me paraît de loin la meilleur idée, ce qui permet de minimiser le nombre d'appels systèmes.

Reply

Marsh Posté le 04-10-2006 à 09:05:13    

Taz a écrit :

mais pour conclure ce thread, je dirais juste : envoie en même ce que tu veux envoyer en même temps. Aggréger les messages pour faire un seul send me paraît de loin la meilleur idée, ce qui permet de minimiser le nombre d'appels systèmes.


 
Voire même créer une structure destinée à contenir l'ensemble des messages; style

typedef struct {
    char text[10][1024];
}t_message;
 
t_message sbuf;


 
Puis tu remplis sbuf.text[0], sbuf.text[1], etc et enfin tu envoies  
send(..., &sbuf, sizeof(sbuf), 0)
 
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

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