Rechercher : dans
Par :

[PERL] lecture/écriture sur une socket

Dernière réponse le 26 nov 2009 à 19:06:07 sephiburp, le 11 aoû 2007 à 12:47:26 
 Signaler ce message aux modérateurs

Bonjour,

J'aimerais faire du client-serveur intéractif en Perl.

J'ai un serveur.pl qui fonctionne correctement, j'ai repris ce script : http://perl.enstimac.fr/DocFr/perlipc.html#serveurs%20tcp%20­avec%20io::socket


Et j'ai un client.pl dont voici le code :

use IO::Socket;
use warnings;
use strict;

my ($sock, $kidpid);

$sock = IO::Socket::INET->new(Proto     => "tcp",
                              PeerAddr  => "192.168.0.11",
                              PeerPort  => 9000)
                        || die "Failed : $!";
$sock->autoflush(1);

$kidpid = fork();
die "can't fork: $!" if ! defined($kidpid);

if ($kidpid) {
    # PERE : Ecoute des entrées clavier et envoi à la socket
    while (<STDIN>) { print $sock $_; }
} else {
    # FILS : Ecoute de la socket et affichage à l'écran
    while (<$sock>) { print STDOUT $_; }
}

close $sock;


Mon problème :
La connexion réussie, et le client reçoit et affiche les messages d'accueil du serveur.
Mais après la première ligne rentrée au clavier, çà se "bloque". Et le serveur ne recoit même pas cette ligne.

Après un déboggage "approfondi", j'en ai conclu que le processus père n'arrive pas à écrire sur la socket tant que le fils boucle sur cette même socket pour écouter.
En effet, si je ne fais que écrire ou que écouter, cà fonctionne très bien.

J'ai essayer plusieurs scripts client trouvés sur le net et j'en arrive toujours au même problème.
Même celui proposé ici réagit pareil : http://perl.enstimac.fr/DocFr/perlipc.html#client%20interactif%20avec%20io::socket

Je suis sous Windows 2000 et j'utilise Perl 5.8.8
Est-ce à cause de Windows qui gère mal le fork() ou les sockets ?

Merci d'avance pour votre aide !!
Configuration: Windows 2000
Firefox 2.0.0.6

Meilleures réponses pour « [PERL] lecture/écriture sur une socket » dans :
Perl - Les fichiers Voir La notion de filehandle On appelle filehandle (traduisez descripteur de fichier), dans un programme Perl, le nom permettant de manipuler une connexion d'entrée-sortie (les entrées-sorties standards vues précédemment sont connues par les filehandles...
Lire et écrire les partitions Windows (NTFS) VoirUbuntu est parfaitement capable de lire et écrire les partitions Windows, qu'elles soient FAT32 ou NTFS. Cela inclut les partitions de Windows 95, 98, ME, NT, 2000, XP, 2003 et Vista. Mais par défaut, Ubuntu (et Linux en général) peut lire et...
Comment lire un fichier ligne par ligne VoirComment lire un fichier ligne par ligne Préambule Boucle while Syntaxe Exemple Astuces Bonus Boucle for Syntaxe Préambule Une des erreurs les plus communes dans l'apprentissage des scripts "bash" sous GNU/LInux pour lire un fichier...
Lire les sous-titres VoirCertains films possèdent des sous-titres dans un fichier à part, possédant généralement l'extension .srt, .ssa ou .sub. Le plus simple pour lire les sous-titres est de renommer le fichier de sous-titres comme le fichier vidéo (à l'exception de...
Perl - Entrée et sortie standards VoirQu'appelle-t-on entrée standard et sortie standard ? Perl permet d'écrire sur la sortie standard, appelée STDOUT et de lire sur l'entrée standard (STDIN). Il s'agit de deux descripteurs fournis par le système d'exploitation et permettant...
Perl - Caractéristiques du langage VoirFichier source, et interprétation Le fichier source d'un programme écrit en Perl est un simple fichier texte dont l'extension est par convention .pl. Ce fichier source doit être un fichier texte non formatté, c'est-à-dire un fichier texte dans sa...
Les fonctions de l'API Socket VoirLes fonctions des sockets en détail La fonction socket() La création d'un socket se fait grâce à la fonction socket() : int socket(famille,type,protocole) famille représente la famille de protocole utilisé (AF_INET pour TCP/IP utilisant une...

1

sephiburp, le 19 aoû 2007 à 11:44:22

Je relance ma question,
Une idée chez quelqu'un ?

Répondre à sephiburp

2

lami20j, le 19 aoû 2007 à 16:02:32
  • +2

Salut,

voici un exemple, à toi d'adapter
server

#!/usr/bin/perl
use strict;use warnings;
use IO::Socket;

my $serveur = IO::Socket::INET->new(LocalPort => 10000,
                                    Type      => SOCK_STREAM,
                                    Reuse     => 1,
                                    Listen    => 10)
or die "Impossible serveur tcp sur le port 10000 : $@\n";

while (my $client = $serveur->accept()) {
  next if my $pid = fork;
  close($serveur);
  print "*** Debut de connexion ***\n";
  print $client "Bienvenu sur le SERVER !\n--- Je suis PID $$ ---\n";
  while( my $rep = <$client>) {
    print $rep;
    if ( $rep =~ /^QUIT/i) {
      close($client);
    }
    print "*** Fin de connexion sur PID $$ ***\n";
    exit;
  }continu {
    close($client);
  }
}
$SIG{CHLD} = 'IGNORE';
__END__
le client
#!/usr/bin/perl
use strict;use warnings;
use IO::Socket;

my $socket = IO::Socket::INET->new(Proto    => "tcp",
                                   PeerAddr => "10.0.0.5",
                                   PeerPort => 10000)
or die "Failed : $@\n";

print "*** Debut de connexion ***\n";
while(my $reponse=<$socket>){
  print "Le serveur a dit : $reponse";
  print $socket "Au revoir SERVEUR!!!\n";
}
print "*** Fin de connexion ***\n";
__END__
Sur le serveur
lami20j@deb:~$ perl ccm.pl
*** Debut de connexion ***
Au revoir SERVEUR!!!
*** Fin de connexion sur PID 12855 ***
Sur le client
lami20j@debian:~$ perl ccm.pl
*** Debut de connexion ***
Le serveur a dit : Bienvenu sur le SERVER !
Le serveur a dit : --- Je suis PID 12855 ---
*** Fin de connexion ***
lami20j@debian:~$

lami20j

Répondre à lami20j

3

sephiburp, le 19 aoû 2007 à 22:03:52

Bonsoir lami, merci pour ta réponse.
Mais le client que tu proposes ne fait que lire la socket.

J'aimerais avoir un client qui écrit et lit simultanément sur une socket, d'où l'utilisation d'un fork avec un père qui écrit et un fils qui lit.
Rappel du problème : le père bloque sur l'écriture de la socket tant que le fils boucle pour la lire.

J'essaierai tout de même les paramètres de ton exemple que je n'ai jamais utilisé (Type=>SOCK_STREAM pour la création de l'objet et $SIG{CHLD}='IGNORE' ...)

Répondre à sephiburp

4

lami20j, le 19 aoû 2007 à 22:46:55

Re,

Mais le client que tu proposes ne fait que lire la socket.
Il écrit aussi Au revoir SERVEUR !!!

J'aimerais avoir un client qui écrit et lit simultanément sur une socket, d'où l'utilisation d'un fork avec un père qui écrit et un fils qui lit.
Rappel du problème : le père bloque sur l'écriture de la socket tant que le fils boucle pour la lire.


Ok, je vais voir ça ;-) lami20j

Répondre à lami20j

5

philippe, le 12 jun 2008 à 14:44:24

Petite remarque hors sujet.

Le mot socket est masculin.

Sinon, on écrit aussi une soquette, mais c'est autre chose.

Sinon, pour compléter un peu le sujet, il t'est possible de faire un thread plutôt que de créer un processus avec un fork pour lire et écrire simultanément sur ton socket.

Répondre à philippe

6

lami20j, le 14 jun 2008 à 23:29:08

Toujours hors sujet

Semble-t-il que certains traducteurs spécialisés pense que socket c'est un féminin, vu qu'il s'agit d'une association d'une adresse IP et d'un numéro de port

Exemple :

Livre TCP/IP 3ème édition, Edition O'Reilly - Traduction Emmanuel Chaput et Stéphane Larroque


Je cite depuis Page 50
L'association d'une adresse IP et d'un numéro de port est appelée une socket

Livre Perl en Action, Edition O'Reilly - Traduction Sébastien Blondeel

Je cite depuis Page 702

La fonction socket crée une socket, la fonction bind donne à une socket un nom local, la fonction connect connecte la socket à une autre socket, qui peut être distante, la fonction listen prépare une socket à recevoir des connexions d'autres socket ......

On peut communiquer via une socket ...


Livre Programmation en Perl, 3ème edition, Editon O'Reilly - Traduction Philippe Bruhat, Kai Carver et Gérald Sédrati

Je cite
Glosaire Page 974

socket - ..... La chose la plus importante concernant une socket est son adresse réseau.....

Page 409
Bien que les sockets aient été inventées sur BSD, elles se sont rapidement répandues....

Page 746

Cette fonction ouvre une socket du type spécifié...


Livre Programmation système en C sous Linux par Christophe Blaess

Je cite
Page 132

Ces données peuvent être transmises sur une socket TCP/IP avec une priorité ....

Page 516

Les programmes offrant des services réseau peuvent choisir d'utiliser leur propre système de connexion, construisant une socket et restant à l'écoute ....

106485010510997108

Répondre à lami20j

7

Philipp, le 15 jun 2008 à 11:22:50

Effectivement, tes sources sont fiables, même si je trouve que ça ne sonne pas très bien.

Dans mon message précédent, je proposais l'utilisation des threads.

Débutant dans ce langage, je viens de découvrir à quel point le modèle de thread est mauvais en PERL.

Les variables ne sont pas partagées par défaut entre les threads. Il faut préciser le mot clé shared pour les rendre partagées. Bon, pourquoi pas.

Toutefois, les types structurés ou objets sont partageables que si les éléments qui le composent sont partageables. Ainsi, il devient impossible de partager un socket. Ainsi, la solution d'avoir un thread qui consomme et l'autre qui écrit n'est plus viable.

Quelqu'un saurait-il comment outrepasser cette limitation du modèle de thread de PERL ?

Répondre à Philipp

8

lami20j, le 15 jun 2008 à 11:34:17

Salut,

ça pourra peut être t'aider ;-)
http://www.developpez.net/forums/showthread.php?t=446880
106485010510997108

Répondre à lami20j

9

michto, le 25 nov 2009 à 17:53:21

Bien j'avou que j'ai exactement le meme soucis que toi, peu importe les codes testés, je ne peux que lire dans la socket, ou que ecrire dessus, mais pas les deux, et ce soucis ne se pose que sous windows ..

sous linux, aucun soucis, donc j'en deduis comme toi, un soucis de fork() avec windows..

Pour ce qui concerne les threads, je ne vois pas trop comment organiser mon code pour faire le serveur.

Si il y aurait kk1 pour eclairer cette situation .. Merci :)

Répondre à michto

10

 m1chto, le 26 nov 2009 à 19:06:07

Re bonjour,

bien voila, apres quelques tests, j'ai reussi a faire fonctionner le premier code que tu as posté sur XP, il m'as fallu placer cette commande " waitpid($pid,0); ", juse avant la boucle while du pid pere ..

voila dis moi si pour toi, cela resous le soucis

Répondre à m1chto