TCP-IP Pb recv bloquant et terminaison de processus - C++ - Programmation
Marsh Posté le 15-04-2003 à 03:17:57
... et si tu pouvais, voudrais-tu rendre ton recv non-bloquant ?
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 :
|
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
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
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.
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();
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