TCP-IP Pb recv bloquant et terminaison de processus

TCP-IP Pb recv bloquant et terminaison de processus - C++ - Programmation

Marsh Posté le 14-04-2003 à 12:13:06    

bonjour,
 
 
J'ai un programme qui ecoute sur un port TCP pour renvoyer sur le port serie, l initialisation se passe bien mais lorsque je veux quitter ca bloque.
 
Dans mon thread principal je fais un ShutDown qui fait un
WaitForSingleObject de mon TCPThread
 
Dans mon TCPThread , je fais un accept, puis je boucle sur un recv bloquant. Le pb est que comme il bloque , tant que je n ai pas recu de donnees , il ne continue pas.
 
Comment faire pour debloquer mon recv ? l action de fermer la socket permet de quitter cette fonction (avec une erreur evidemment) ? ou alors y a t il une autre methode / astuce ?
 
PS : je ne peux pas rendre mon recv non bloquant :-(  
 
Merci


Message édité par xilebo le 14-04-2003 à 15:38:48
Reply

Marsh Posté le 14-04-2003 à 12:13:06   

Reply

Marsh Posté le 14-04-2003 à 15:56:47    

up

Reply

Marsh Posté le 14-04-2003 à 16:35:16    

code source ?

Reply

Marsh Posté le 15-04-2003 à 03:17:57    

... et si tu pouvais, voudrais-tu rendre ton recv non-bloquant ?

Reply

Marsh Posté le 15-04-2003 à 09:38:07    

bah ... je sais rendre un recv non bloquant (fcntl ) mais je pense que de rendre non bloquant pour quitter la fonction puis rendre bloquant a  nouveau (car je travaille en bloquane) risque d etre bourrin/dangereux (je ne sais pas encore comment mon prog reagirait)
 
Par contre, comment travailer en non bloquant sachant que la plupart du temps je ne recois pas de donnees... je trouvais bien que la fonction attende pour moi
 
Je n ai pas le code de la fonction, je suppose qu en  mode bloquant, la fonction boucle sur une variable ? si je travaille en mode non bloquant je n'ai qu a faire la meme chose ? mais je trouve que mon process travaillerait beaucoup a boucler :
ex de code (avec recv non bloquant)
 

Code :
  1. while (IsConnected) {
  2.      int ret;
  3.      ret = recv(...);
  4.      if ret == (SOCKET_ERROR ){
  5.      // traiter l erreur et terminer la connexion le cas echeant
  6. }
  7.    if (ret == 0) {
  8.     // aucun octet recu donc boucler a nouveau , c la que je pense que la boucle passerait souvent
  9. }
  10.   if (ret > 0) {
  11. // octets recus ... faire le traitement
  12. }
  13. }

 
 
 
est ce bon ?  
 
 
D 'autre part je me suis apercu que la fonction accept est egalement bloquante, et donc si je suis en attente d une connexion et que je veux quitter l application, mon process est egalement bloqué sur cette fonction.
Dois je gerer mes connexions dans un thread dedié que je tue lors d une terminaison ?
 
 
merci de vos reponses

Reply

Marsh Posté le 15-04-2003 à 15:37:52    

pour le non-bloquant, je te conseil plutot d'utiliser select, avec un timeout.
voici un bout de code épuré:
 
void get_events()
{
 
fd_set  rfds;
struct timeval ti;
int i,n;
char buff[2000];
unsigned char event=0;  
 
  rfds=rb.cfds;  // select va ecraser le contenu de rfds
  ti.tv_sec=1;
  ti.tv_usec=0;
  select(FD_SETSIZE,&rfds,0,0,&ti); // Attente d'activite sur l'une des sockets sockINLOG,connAPP,sockAPP, ou sockLIST   (avec timeout)
  if ((FD_ISSET(rb.connAPP,&rfds))) // applet connectee parle
  {
    n=read(rb.connAPP,buff,2000);
    if (n>0)   // un envoie non nul ?
      printf("recu %d octets\n",n);
  }
 
  if (FD_ISSET(rb.sockAPP,&rfds)) post_event(EV_APPLET_CONNECT,buff,0); // une applet veut se connecter
   
  if ((FD_ISSET(rb.sockINLOG,&rfds))) // reception de logs
  {
    n=recv(rb.sockINLOG,buff,3000,0);
    ...
  }
 
  if ((FD_ISSET(rb.sockLIST,&rfds)))
  {
    rb.connLIST=accept(rb.sockLIST,(sockaddr*)&rb.addrLISTPEER,&rb.len);  // bah, on l'accepte
   
    read(rb.connLIST,buff,1);
    ...
    }  
}
 
 
main()
{
  ...
  FD_ZERO(&rb.cfds); // Monitoring des entrees/sorties:
  FD_SET(rb.sockAPP,&rb.cfds); // au debut ya juste la socket qui listen les connections
  FD_SET(rb.sockINLOG,&rb.cfds);  // les log
  FD_SET(rb.sockLIST,&rb.cfds);   // et l'ecoute des requetes serverList
 
  while(on)
  {
    get_events();
    ...
  }    
}
 
 
l'essentiel de l'attente se fait au nivo du select; dans l'exemple c pas du multithread

Reply

Marsh Posté le 15-04-2003 à 16:07:55    

je n ai pas bien compris... le select permet de bloquer temporairement le read ? quel est la difference si j endors le thread pendant le meme temps ?  
 
ou alors ca signifie que , si je mets un timeout de 1 sec , il va rester bloqué sur le read pendant 1 sec puis quitter si rien n est lu ? (et donc reboucler a nouveau)
 
dans ce cas , effectivement ca peut etre interessant, c les avantages du bloquant sans les inconvenient (bloquant = timeout infini)
 
par contre , mon pb est que je suis sous windows donc la fonction select et les macros FD_ je ne sais pas si je les ai.
 
subsidiaire : ca marche avec les ports serie car j ai le pb inverse sur des ports serie (sous windows port serie non bloquant donc ca boucle a l infini)
 
 
en tout cas merci.
 
 
 
 

Reply

Marsh Posté le 15-04-2003 à 18:02:24    

sous windows t'as acces à select, et autre FD_SET ...
(#include <winsock.h> ); tu peux jeter un oeil à winsock.hlp si tu le trouves
 
le select() marche avec des file descriptor, donc ca marche avec des fichiers ou des sockets; pour le port com, si tu recupere un fd ca devrait marcher.
 
le select() écoute s'il y a un evenement sur l'un des fd du fd_set; il bloque jusqu'à l'appartion d'un evenement ou jusqu'a la fin du timeout; à la sortie du select() ya plus qu'a tester quel fd à debloquer le select(), avec FD_ISSET();

Reply

Sujets relatifs:

Leave a Replay

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