Il se connecte sur un serveur TCP, et écoute ce qu'on lui envoie jusqu'à
ce qu'il reçoive un caractère spécial qui lui indique la fin du message.
A partir de ce message, il effectue un tratement, puis il répond au serveur.
Cependant, aléatoirement, il peut être succeptible d'envoyer, à sa
propre initiative, via la socket, des informations au serveur.
Voici le squelette de mon programme:
use IO::Socket;
use IO::Select;
...
Création de la socket et connexion au serveur
$SIG{ALRM}= sub { &envoiealeatoire()}
alarm(5);
LOOP: Boucle sans fin
RECEP: Boucle sans fin
Sortie de la boucle sur réception grace
à $s->can_read(10)
FINRECEP
Traitement de la réponse
Envoie au serveur la réponse
FINLOOP
sub envoiealeatoire{
alarm 0;
Envoie via la socket d'un message au serveur.
alarm aléatoire.
}
Mon problème est le suivant:
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur la
socket, mais rien.
Y a t'il une explication ?
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm du module Time::HiRes), il la traite en envoyant, via la socket, un message, mais dès qu'il fini ce traitement, le programme reprend son execution APRES le $s->can_read(10) Tout se passe comme si je venais alors de recevoir quelque chose, sur la socket, mais rien. Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici le SIGALARM). C'est le comportement normal.
Par ailleurs, il faut minimiser le plus possible la quantité de code dans un handler de signal. L'idéal : juste changer la valeur d'une variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux effets. Effet direct : positionner un flag à 1. Effet indirect: interrompre l'attente. En sortie de lecture, vous testez le flag. Si il est à un 1 vous déclencher votre action d'envoi, vous remettez le flag à zéro. et vous reprenez l'attente. Sinon, vous faites le traitement normal.
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur
la socket, mais rien.
Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici
le SIGALARM). C'est le comportement normal.
Par ailleurs, il faut minimiser le plus possible la quantité de code
dans un handler de signal. L'idéal : juste changer la valeur d'une
variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux
effets. Effet direct : positionner un flag à 1. Effet indirect:
interrompre l'attente. En sortie de lecture, vous testez le flag. Si
il est à un 1 vous déclencher votre action d'envoi, vous remettez le
flag à zéro. et vous reprenez l'attente. Sinon, vous faites le
traitement normal.
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm du module Time::HiRes), il la traite en envoyant, via la socket, un message, mais dès qu'il fini ce traitement, le programme reprend son execution APRES le $s->can_read(10) Tout se passe comme si je venais alors de recevoir quelque chose, sur la socket, mais rien. Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici le SIGALARM). C'est le comportement normal.
Par ailleurs, il faut minimiser le plus possible la quantité de code dans un handler de signal. L'idéal : juste changer la valeur d'une variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux effets. Effet direct : positionner un flag à 1. Effet indirect: interrompre l'attente. En sortie de lecture, vous testez le flag. Si il est à un 1 vous déclencher votre action d'envoi, vous remettez le flag à zéro. et vous reprenez l'attente. Sinon, vous faites le traitement normal.
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm du module Time::HiRes), il la traite en envoyant, via la socket, un message, mais dès qu'il fini ce traitement, le programme reprend son execution APRES le $s->can_read(10) Tout se passe comme si je venais alors de recevoir quelque chose, sur la socket, mais rien. Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici le SIGALARM). C'est le comportement normal.
En effet.
Par ailleurs, il faut minimiser le plus possible la quantité de code dans un handler de signal. L'idéal : juste changer la valeur d'une variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux effets. Effet direct : positionner un flag à 1. Effet indirect: interrompre l'attente. En sortie de lecture, vous testez le flag. Si il est à un 1 vous déclencher votre action d'envoi, vous remettez le flag à zéro. et vous reprenez l'attente. Sinon, vous faites le traitement normal.
Effectivement, cela me semble parfaitement jouable.
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur
la socket, mais rien.
Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici
le SIGALARM). C'est le comportement normal.
En effet.
Par ailleurs, il faut minimiser le plus possible la quantité de code
dans un handler de signal. L'idéal : juste changer la valeur d'une
variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux
effets. Effet direct : positionner un flag à 1. Effet indirect:
interrompre l'attente. En sortie de lecture, vous testez le flag. Si
il est à un 1 vous déclencher votre action d'envoi, vous remettez le
flag à zéro. et vous reprenez l'attente. Sinon, vous faites le
traitement normal.
Effectivement, cela me semble parfaitement jouable.
Le fait de ralentir le traitement du handler de signal par l'envoi d'un
message via socket peut aussi avoir un effet pervers, dans la mesure où
l'envoi peut générer une attente et donc figer le programme jusqu'à se
que cela finisse.
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm du module Time::HiRes), il la traite en envoyant, via la socket, un message, mais dès qu'il fini ce traitement, le programme reprend son execution APRES le $s->can_read(10) Tout se passe comme si je venais alors de recevoir quelque chose, sur la socket, mais rien. Y a t'il une explication ?
Oui. Votre instruction d'attente a été interrompue par un signal (ici le SIGALARM). C'est le comportement normal.
En effet.
Par ailleurs, il faut minimiser le plus possible la quantité de code dans un handler de signal. L'idéal : juste changer la valeur d'une variable.
Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux effets. Effet direct : positionner un flag à 1. Effet indirect: interrompre l'attente. En sortie de lecture, vous testez le flag. Si il est à un 1 vous déclencher votre action d'envoi, vous remettez le flag à zéro. et vous reprenez l'attente. Sinon, vous faites le traitement normal.
Effectivement, cela me semble parfaitement jouable.
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire ce que lui envoie le serveur) d'envoyer lui aussi des données au serveur... qui ne les lit pas car il attend que votre client ait fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec des lectures/écritures non-bloquantes pour éviter ce problème classique de communication bi-directionnelle.
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
Le fait de ralentir le traitement du handler de signal par l'envoi
d'un message via socket peut aussi avoir un effet pervers, dans la
mesure où l'envoi peut générer une attente et donc figer le programme
jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte
mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire
ce que lui envoie le serveur) d'envoyer lui aussi des données au
serveur... qui ne les lit pas car il attend que votre client ait
fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec
des lectures/écritures non-bloquantes pour éviter ce problème
classique de communication bi-directionnelle.
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire ce que lui envoie le serveur) d'envoyer lui aussi des données au serveur... qui ne les lit pas car il attend que votre client ait fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec des lectures/écritures non-bloquantes pour éviter ce problème classique de communication bi-directionnelle.
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire ce que lui envoie le serveur) d'envoyer lui aussi des données au serveur... qui ne les lit pas car il attend que votre client ait fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec des lectures/écritures non-bloquantes pour éviter ce problème classique de communication bi-directionnelle.
C'est heureusement le cas de mon programme serveur.
Je viens de faire la modif, j'arrive à traiter correctement mon problème, même avec un ualarm de 10000 µs (pas la peine de descendre plus bas, je n'en ai pas l'utilité).
Mon programme serveur encaisse alors plus de 3 x 100 requêtes à la seconde. Analyse chacune d'elles au niveau syntaxique, et aiguille chaque trame vers le bon client en fonction de certains critères.
Mon programme fait partie d'un projet d'application de Contrôle d'Accès de véhicule dans un parking. Jamais je n'aurais penser aller aussi vite.
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps réel, ce doit être une question de temps < milliseconde. En ce qui me concerne, une réponse de cette envergure me convient tout a fait.
Le fait de ralentir le traitement du handler de signal par l'envoi
d'un message via socket peut aussi avoir un effet pervers, dans la
mesure où l'envoi peut générer une attente et donc figer le programme
jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte
mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire
ce que lui envoie le serveur) d'envoyer lui aussi des données au
serveur... qui ne les lit pas car il attend que votre client ait
fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec
des lectures/écritures non-bloquantes pour éviter ce problème
classique de communication bi-directionnelle.
C'est heureusement le cas de mon programme serveur.
Je viens de faire la modif, j'arrive à traiter correctement mon
problème, même avec un ualarm de 10000 µs (pas la peine de descendre
plus bas, je n'en ai pas l'utilité).
Mon programme serveur encaisse alors plus de 3 x 100 requêtes à la
seconde. Analyse chacune d'elles au niveau syntaxique, et aiguille
chaque trame vers le bon client en fonction de certains critères.
Mon programme fait partie d'un projet d'application de Contrôle d'Accès
de véhicule dans un parking.
Jamais je n'aurais penser aller aussi vite.
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.
En ce qui me concerne, une réponse de cette envergure me convient tout a
fait.
Le fait de ralentir le traitement du handler de signal par l'envoi d'un message via socket peut aussi avoir un effet pervers, dans la mesure où l'envoi peut générer une attente et donc figer le programme jusqu'à se que cela finisse.
Certes... Le véritable problème est l'interblocage (ou «étreinte mortelle» ou «deadlock») :
Le serveur envoie des données mais votre client décide (avant lire ce que lui envoie le serveur) d'envoyer lui aussi des données au serveur... qui ne les lit pas car il attend que votre client ait fini de lire. Résultat : blocage...
Il faut (au minimum) que l'un des deux programmes soient écrit avec des lectures/écritures non-bloquantes pour éviter ce problème classique de communication bi-directionnelle.
C'est heureusement le cas de mon programme serveur.
Je viens de faire la modif, j'arrive à traiter correctement mon problème, même avec un ualarm de 10000 µs (pas la peine de descendre plus bas, je n'en ai pas l'utilité).
Mon programme serveur encaisse alors plus de 3 x 100 requêtes à la seconde. Analyse chacune d'elles au niveau syntaxique, et aiguille chaque trame vers le bon client en fonction de certains critères.
Mon programme fait partie d'un projet d'application de Contrôle d'Accès de véhicule dans un parking. Jamais je n'aurais penser aller aussi vite.
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps réel, ce doit être une question de temps < milliseconde. En ce qui me concerne, une réponse de cette envergure me convient tout a fait.
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps réel, ce doit être une question de temps < milliseconde.
Qui a bien pu vous faire croire ça ? ;-) La bonne définition du « temps réel » est « garantir un temps de réponse compatible avec le besoin ».
voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...
Je cite : « ... Perl n'est probablement pas bien adapté pour des systèmes embarqués temps-réel,...».
Il y a deux nuances ici :
1- "pas bien adapté" ne veut pas dire "inutilisable" ;-)
2- "systèmes embarqués temps-réel". Pour moi le plus important est le terme "embarqués" qui implique (souvent) une fiabilité garantie...
De toutes manières, la plupart des Unix ne sont pas réellement adaptés au vrai temps-réel. Par exemple, il est toujours possible d'interrompre (momentanément) une tâche quelconque comme par exemple la lecture d'un film ou d'un fichier audio rien qu'en lançant une bonne grosse compilation (qui monopolise la ressource critique qui dans ce cas est le disque). On peut s'en sortir en gérant finement les priorités ou en utilisant des noyaux bien conçus mais ce n'est pas garanti à la base...
Bon. D'accord ! Je pousse le bouchon un peu loin ;-)
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.
Qui a bien pu vous faire croire ça ? ;-) La bonne définition du
« temps réel » est « garantir un temps de réponse compatible avec
le besoin ».
voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...
Je cite : « ... Perl n'est probablement pas bien adapté pour des
systèmes embarqués temps-réel,...».
Il y a deux nuances ici :
1- "pas bien adapté" ne veut pas dire "inutilisable" ;-)
2- "systèmes embarqués temps-réel". Pour moi le plus important est le
terme "embarqués" qui implique (souvent) une fiabilité garantie...
De toutes manières, la plupart des Unix ne sont pas réellement adaptés
au vrai temps-réel. Par exemple, il est toujours possible
d'interrompre (momentanément) une tâche quelconque comme par exemple
la lecture d'un film ou d'un fichier audio rien qu'en lançant une
bonne grosse compilation (qui monopolise la ressource critique qui
dans ce cas est le disque). On peut s'en sortir en gérant finement les
priorités ou en utilisant des noyaux bien conçus mais ce n'est pas
garanti à la base...
Bon. D'accord ! Je pousse le bouchon un peu loin ;-)
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps réel, ce doit être une question de temps < milliseconde.
Qui a bien pu vous faire croire ça ? ;-) La bonne définition du « temps réel » est « garantir un temps de réponse compatible avec le besoin ».
voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...
Je cite : « ... Perl n'est probablement pas bien adapté pour des systèmes embarqués temps-réel,...».
Il y a deux nuances ici :
1- "pas bien adapté" ne veut pas dire "inutilisable" ;-)
2- "systèmes embarqués temps-réel". Pour moi le plus important est le terme "embarqués" qui implique (souvent) une fiabilité garantie...
De toutes manières, la plupart des Unix ne sont pas réellement adaptés au vrai temps-réel. Par exemple, il est toujours possible d'interrompre (momentanément) une tâche quelconque comme par exemple la lecture d'un film ou d'un fichier audio rien qu'en lançant une bonne grosse compilation (qui monopolise la ressource critique qui dans ce cas est le disque). On peut s'en sortir en gérant finement les priorités ou en utilisant des noyaux bien conçus mais ce n'est pas garanti à la base...
Bon. D'accord ! Je pousse le bouchon un peu loin ;-)
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>