OVH Cloud OVH Cloud

vérifier l'arriver de messages sur plusieurs sockets

4 réponses
Avatar
Scetbon Cyril
Bonjour,

J'ai >1 serveurs en écoute sur # ports et je vérifie si qqchose est
arrivé sur l'un des ports pour le traiter.
Cependant j'ai une interrogation qui me travaille même si le bout de
code suivant fait ce que je veux :-)
En effet si je ne mets pas la petite attente signalée + bas, le
processus père voie des données sur un port x tout de suite après avoir
lu des données sur un port y, alors qu'il n'y a rien sur le port x!!!

Qq'un aurait il une explication ?

while(1)
{
$rin=$rout='';
vec($rin,fileno($_),1)=1 for (@sockets);
($numready)=select($rout=$rin,undef,undef,undef);
for my $socket (@sockets)
{
next if !vec($rout,fileno($socket),1);
$socket->recv($text,4000);
if(!($pid=fork))
{
@data=map {uc unpack("H*",$_)} split //,$text;
create_response $socket|| next;
$socket->send($text);
exit 0;
}
else
{select(undef,undef,undef,0.05)} <= C'EST LA !!!
}
}

4 réponses

Avatar
Paul GABORIT
À (at) Thu, 08 Apr 2004 12:01:09 +0200,
Scetbon Cyril écrivait (wrote):
Cependant j'ai une interrogation qui me travaille même si le bout de code
suivant fait ce que je veux :-)
En effet si je ne mets pas la petite attente signalée + bas, le processus
père voie des données sur un port x tout de suite après avoir lu des données
sur un port y, alors qu'il n'y a rien sur le port x!!!

Qq'un aurait il une explication ?


A priori un 'select' qui déclenche sur un file descriptor (en lecture) alors
que celui ne propose rien à lire le fait pour signaler la fermeture de ce file
descriptor. Mais cela ne semble pas le cas ici (bien que vous ne traitiez pas
cette situation).

De plus, le fait de passer par le 'select' d'attente ne change pas les valeurs
stockées dans $rout. Donc, ça ne peut pas se passer dans la même boucle. Il
doit y avoir un nouveau passage sur le 'select' réel. Peut-être est-ce du à
une interruption suite au fork en cours... Dans ce cas, vous devriez tester la
valeur de $numready avant de traiter @sockets. Si c'est une valeur négative ou
nulle, il est inutile de passer dans la boucle de traitement.

while(1)
{
$rin=$rout='';
vec($rin,fileno($_),1)=1 for (@sockets);
($numready)=select($rout=$rin,undef,undef,undef);
for my $socket (@sockets)
{
next if !vec($rout,fileno($socket),1);
$socket->recv($text,4000);
if(!($pid=fork))
{
@data=map {uc unpack("H*",$_)} split //,$text;
create_response $socket|| next;
$socket->send($text);
exit 0;
}
else
{select(undef,undef,undef,0.05)} <= C'EST LA !!!
}
}


--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Scetbon Cyril
Paul GABORIT wrote:
À (at) Thu, 08 Apr 2004 12:01:09 +0200,
Scetbon Cyril écrivait (wrote):

Cependant j'ai une interrogation qui me travaille même si le bout de code
suivant fait ce que je veux :-)
En effet si je ne mets pas la petite attente signalée + bas, le processus
père voie des données sur un port x tout de suite après avoir lu des données
sur un port y, alors qu'il n'y a rien sur le port x!!!

Qq'un aurait il une explication ?



A priori un 'select' qui déclenche sur un file descriptor (en lecture) alors
que celui ne propose rien à lire le fait pour signaler la fermeture de ce file
descriptor. Mais cela ne semble pas le cas ici (bien que vous ne traitiez pas
cette situation).

De plus, le fait de passer par le 'select' d'attente ne change pas les valeurs
stockées dans $rout. Donc, ça ne peut pas se passer dans la même boucle. Il
doit y avoir un nouveau passage sur le 'select' réel. Peut-être est-ce du à
une interruption suite au fork en cours...
je veux bien, mais cela ce fait sur une autre socket que celle sur

laquelle est arrivé un message, alors quel rapport ???
mais si le select est fait à nouveau il devrait toujours voir un message
sur la même socket et non une autre.
Dans ce cas, vous devriez tester la
valeur de $numready avant de traiter @sockets. Si c'est une valeur négative ou
nulle, il est inutile de passer dans la boucle de traitement.


while(1)
{
$rin=$rout='';
vec($rin,fileno($_),1)=1 for (@sockets);
($numready)=select($rout=$rin,undef,undef,undef);
for my $socket (@sockets)
{
next if !vec($rout,fileno($socket),1);
$socket->recv($text,4000);
if(!($pid=fork))
{
@data=map {uc unpack("H*",$_)} split //,$text;
create_response $socket|| next;
$socket->send($text);
exit 0;
}
else
{select(undef,undef,undef,0.05)} <= C'EST LA !!!
}
}






Avatar
Paul GABORIT
À (at) Sat, 10 Apr 2004 23:00:18 +0200,
Scetbon Cyril écrivait (wrote):
je veux bien, mais cela ce fait sur une autre socket que celle sur laquelle
est arrivé un message, alors quel rapport ??? mais si le select est fait à
nouveau il devrait toujours voir un message sur la même socket et non une
autre.


L'interruption du 'select' peut se faire à n'importe quel moment (et donc sur
n'importe quel file descriptor). Un 'fork' n'est pas une opération
anodine. Elle peut avoir des effets sur tous les file descriptor
ouverts. Avez-vous testé la valeur de $numready ?

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Scetbon Cyril
Paul GABORIT wrote:
À (at) Sat, 10 Apr 2004 23:00:18 +0200,
Scetbon Cyril écrivait (wrote):

je veux bien, mais cela ce fait sur une autre socket que celle sur laquelle
est arrivé un message, alors quel rapport ??? mais si le select est fait à
nouveau il devrait toujours voir un message sur la même socket et non une
autre.



L'interruption du 'select' peut se faire à n'importe quel moment (et donc sur
n'importe quel file descriptor). Un 'fork' n'est pas une opération
anodine. Elle peut avoir des effets sur tous les file descriptor
ouverts. Avez-vous testé la valeur de $numready ?
c'était ça !

en fait le fork doit générer un signal sur les fds.