Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1301 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  [perl embed] Probleme socket

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[perl embed] Probleme socket

n°1345066
sundevil
Posté le 12-04-2006 à 15:15:53  profilanswer
 

Bonjour a tous,
 
Je doit actuellement developper un projet de jeu en reseau en C perl embarquer et jai un probleme de socket.
 
Je vous explique mon probleme:
 
Je fait un select dans mon serveur pour savoir sur quelle connection je doit lire des donnees a lire, ensuite jenvoie le file descriptor a mon perl pour lire les donner sur ma socket. Voici ma fonction perl de lecture de donnees:
 
sub     my_read($$)
{
    my $fd = new IO::Handle;
    my $cs = $_[0];
    $fd->fdopen($cs, "r" );
    my $buf = $_[1];
    print("cs = $cs\n" );
    $fd->sysread($buf, 3);
    print("$buf\n" );
    $fd->close();
    return ("$buf" );
}
 
Tout se passe bien jusquau retour au C ou la le probleme se pause. Lorsque je refait un select sur mon file descriptor, il me dit "Bad File descriptor" et la je n'arrive pas a trouver pourquoi.
 
Si quelqu'un peu m'aider, merci.


Message édité par sundevil le 12-04-2006 à 16:06:17
mood
Publicité
Posté le 12-04-2006 à 15:15:53  profilanswer
 

n°1345125
pospos
Posté le 12-04-2006 à 15:43:44  profilanswer
 

les FH de perl ne sont pas exactement des files descriptors comme en C.
si tu veux le filedescriptor il te faut faire fileno($fd);
Mais attention, sur certains systemes tu risque d'avoir des problemes (ex: windows) car ils n'utilisent pas tous un meme "espace" (je ne trouve pas de terme plus approprié...) pour tous les types de file descriptors (fichier, socket, etc.) et tu risque d'avoir deux filno (== file descriptor pour C) identiques mais l'un designant un fichier et l'autre un socket.
Mais si tu reste sur des sockets ca devrait aller

n°1345178
sundevil
Posté le 12-04-2006 à 16:07:28  profilanswer
 

Ok ok, merci bien mais fileno, je doit lutiliser sur $cs qui est le numero du file descriptor qui vient du C ou sur le $fd qui est un new IO::Handle.

n°1345533
pospos
Posté le 12-04-2006 à 20:58:20  profilanswer
 

ton socket tu l'ouvre en perl ou en C?
 
si tu l'ouvre en C alors il faut que tu le "révouvre" en perl avec new_from_fd (ou un truc du genre) de IO-Handle (plutot IO-Socket d'ailleurs)
 
Si tu l'ouvre en perl alors il faut que tu passe fileno($socket) à C pour qu'il el considere comme un socket.
Attention toute fois: si la variable perl qui contient le socket est detruite alors le socket sera fermé
 
Arf, je viens de relire ton post initial. Tu dis que le probleme se pose quand tu veux réutiliser ton socket, et c'est bien normal: perl l'a fermé!
Et le probleme c'est que meme si tu ne le ferme pas il sera fermé automatiquement des que la variable qui le contient sort du scop (c'est à dire des que ta fonction sera finie...) et ca reviendra au meme.
La solution serait de ne pas l'ouvrire directement mais de le dupliquer. Ainsi seule le dup sera fermé et pas le socket initial.
 
Mais dans tous les cas tu aura de mauvaises perfs avec une telle approche, car chaque read va entrainer un dup sur le socket...
Le mieux serais de garder le socket ouvert dans perl.
Tu fait combien de read sur un meme socket avant de le fermer?

n°1345597
sundevil
Posté le 12-04-2006 à 22:28:00  profilanswer
 

Je fait un nombre inconnue de read sur le socket et comme cest un serveur il ya a une multitude de client et donc de socket et je peux pas multiplier par 2 le nombre de fd (un en C et un en perl) ouvert surtout si ils restent ouvert tout le temps.

n°1345846
pospos
Posté le 13-04-2006 à 11:25:54  profilanswer
 

ce qu'il faudrait alors c'est :
 
- soit ouvrire le socket en perl, et lui laisser la maitrise de sa fermeutre (et du coup il faudra mettre la variable qui le contient quelquepart pendant qu'il rode dans la zone C)
 
- soit tu continu à l'ouvrire et à le fermer en C, mais tu t'arrange pour de le "réouvrire" qu'une seule fois en perl, en le mettant en cache pour els fois suivantes (tu ne l'ouvre que pour le permier read), mais c'est assez dangereux (deux fileno identiques n'indiquent pas forcement le meme socket si le premier a été fermé!), et du coup le mieux est d'appeler un fonction perl qui supprime le socket du cache au moment ou tu le ferme en C!
 
perso je te conseil la premiere solution niveau perf, et le mieux serait d'utiliser l'API perl en C (tu vois comment faire).
Tu ouvre le socket en perl et tu passe à C la variable qui le contient. En C tu range ce SV* quelque part et tu incremente son compteur de reference pour qu'il ne soit pas detruit (et le socket fermé), meme si perl ne le voit plus (SvREFCNT_inc). Ensuite tu en extrait le fileno( le fd pour C), avec l'equivalent de la fonction fileno de perl dans son API C :  
avec sv_arg_io le socket passé par perl

   PerlIO *io = to_perlio(sv_arg_io);
     int fd = io ? PerlIO_fileno(io) : -1;


 
ensuite quand tu appel la fonction my_read en perl tu lui passe simplement le socket perl et ca roule (sans y toucher, ni le fermer à la fin).
Et kand tu veux le fermer il suffit (et il faut!) de descrementer le ref count pour dire à perl de la detruire (et donc de fermer le socket) :
SvREFCNT_dec
 
Et ca devrait rouler.
Mais que veux tu faire en perl exactement? Car ton exemple semble trop simple pour necessiter un interpreteur perl?...
 
Pour la doc (mais tu dois connaitre) :
perlapi
perlguts
et puis va voir les sources XS de Event::Lib pour les maipulation sde socket avec l'API C de perl :
http://search.cpan.org/src/VPARSEV [...] .00/Lib.xs


Message édité par pospos le 13-04-2006 à 12:04:48
n°1345878
sundevil
Posté le 13-04-2006 à 11:46:12  profilanswer
 

Si sa tenait qua moi je ferai tout en C ;), mais cest lecole ou je suis qui nous demande de faire sa,
 
Merci pour ton aide, je pense que je vais reussir a me debrouiller avec sa.

n°1352944
Orion_
Posté le 24-04-2006 à 18:00:52  profilanswer
 

mmh, je profite du topic pour demander aussi, je suis dans la meme ecole que sundevil, et j'ai un petit probleme pour les returns du perl en C, j'ai l'impression que ca "lag".
par exemple je fait un print dans perl genre:

Code :
  1. subs perl_read($$)
  2. {
  3. # ...
  4.   if (tagada)
  5.   {
  6.    print "toto";
  7.    return (-1);
  8.   }
  9.   return (0);
  10. }


 
et en fait quand ca print "toto" en C je recois non pas -1 mais 0, pendant au moins une 20aine d'appel ... et apres seulement je recois -1.
en C j'utilise ca:

Code :
  1. dXSARGS;
  2. call_argv("perl_read", G_ARRAY, args);
  3. ret = SvIV(ST(0));
  4. printf("perlret: %d", ret);


 
je pensais utiliser une sorte de flush ou quelque chose du genre mais j'ai pas trouver :(


Message édité par Orion_ le 24-04-2006 à 18:02:52
n°1353341
pospos
Posté le 25-04-2006 à 10:32:54  profilanswer
 

ca bloque ou ca retourne 0?
Si ca retourne 0 ca n'est pas un probleme de flush mais simplement que "tagada" retourne false
 
Par contre le fait que "toto" ne soit pas affiché immediatement à l'ecran est normal: par defaut la sortie standard est bufferisée par ligne. Donc si tu veux que ca s'affiche immediatement tu dois soit faire "toto\n", soit dire explicitement à l'interpreteur que tu ne veux aucune bufferisation en faisant $|=1 en debut de script.


Message édité par pospos le 25-04-2006 à 10:33:37
n°1353580
Orion_
Posté le 25-04-2006 à 13:58:12  profilanswer
 

non ça bloque pas, ça retourne 0, mais ça affiche toto, (et oui dans l'exemple la j'ai oublier le \n, mais dans mon code il y est), donc en gros quand tagada passe a true, sur la sortie standard j'ai:
 
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: 0
toto
perlret: -1
 
:/

mood
Publicité
Posté le 25-04-2006 à 13:58:12  profilanswer
 

n°1353917
pospos
Posté le 25-04-2006 à 21:39:53  profilanswer
 

regarde perlcall ( http://perldoc.perl.org/perlcall.html )
 
tu dois merder quelquepart sur la stack
 
essai peut etre avec une fonction sans argument, en passant G_NOARGS
 
genre
sub perl_test () {
  return 5;
}
 
pour voir ce qui se passe

n°1354280
Orion_
Posté le 26-04-2006 à 13:12:38  profilanswer
 

mmh, en fait on avais oublier un  XSRETURN_EMPTY;
je pensais que sa returnais quelque chose dans la fonction C, mais visiblement non, ca a regler notre probleme :)

n°1355230
stylerzz
Posté le 27-04-2006 à 15:27:44  profilanswer
 

Hello,
 
bon moi j'ai le meme probleme que sundevil au depart dans son premier post, avec le bad file descriptor et a peu de chose pret le meme style de code en perl embed ..  :-/
 
Si quelqu'un a une idee...? parce que les quelques infos ne m'ont pas bcp aide.. bad file descriptor :s
 
merci

n°1355640
pospos
Posté le 27-04-2006 à 23:59:42  profilanswer
 

vous etes combien la?!!

n°1355755
stylerzz
Posté le 28-04-2006 à 10:11:13  profilanswer
 

bah plusieurs a avoir le meme pb ds la meme ecole ^^
 
L'histoire du bad file descriptor nous bloq et on arrive pas a comprendre pourquoi :-/

n°1355790
pospos
Posté le 28-04-2006 à 10:41:58  profilanswer
 

ca serait pas plus simple que tu demande directement à sundevil?
Car d'une part je ne connais pas ton code, et d'autre part c'est assez chiant de debugger ce genre de truc "à distance", et de plus bidouiller l'API C de perl ne fait pas vraiment partie de mes occupations quotidiennes


Message édité par pospos le 28-04-2006 à 10:42:49
n°1355815
stylerzz
Posté le 28-04-2006 à 11:05:30  profilanswer
 

Bah justement je suis a la recherche de sundevil mais etant donne la taille de la promo je ne connais pas forccement les pseudos de tous les mecs, on a le meme pb de bad file descriptor et la on essaye qqs trucs mais ca ne passe pas trop :x
 
En gros pour resumer le truc, ca commence en C, creation socket, on fait notre select, on passe en perl(embed) a qui on passe en param le file descriptor, qu il va reouvrir, pour qu'il puisse taffer dessus en recuperant les infos et en les traitant, mais quand il finit le taff du perl et que le C reprend le relais derriere, on se mange un bad file descriptor quand on test la valeur de retour du select.. pas easy :-/


Message édité par stylerzz le 28-04-2006 à 11:07:19
n°1355852
stylerzz
Posté le 28-04-2006 à 12:02:39  profilanswer
 

bon ben c'est bon j'ai trouve, c'etait un probleme d'open de fd, fallait faire un "<&" et pas un "<&=" comme on faisait :-/

n°1355976
pospos
Posté le 28-04-2006 à 14:24:02  profilanswer
 

dup2, ce dont je parlait dans les permiers message

n°1355982
pospos
Posté le 28-04-2006 à 14:25:52  profilanswer
 

et franchement je trouve que ca serait bcp plus simple d'ouvrirer et de gerer le socket en perl, car on peut tre facilement passer du fh (perl) au fd (C) avec fileno(), mais l'inverse est nettement plsu chiant (et moins efficace, et porteur de bugs...)

n°1357229
stylerzz
Posté le 01-05-2006 à 16:22:07  profilanswer
 

bah vi mais le but du projet est pas forcement  d'etre au plus simple :/

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  [perl embed] Probleme socket

 

Sujets relatifs
[perl] ouverture de fichier d'extension particuliere.[JAVA3D] problème de transparence
[VBS] Probleme avec SQL - timeoutProblème de précision
Problème avec J2SDK[RMI] problème de stub
[SCRIPT WMI] Problème de permission avec Windows 98please ....help : probleme de set
[Resolu] probleme sur un scriptproblème de compatibilité JS Firefox / IE
Plus de sujets relatifs à : [perl embed] Probleme socket


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR