• Publicidad

Por favor, una ayudita con IO::Socket

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Notapor jc.morataya » 2009-06-15 14:15 @635

Hola Explorer,

Fíjate que estuve revisando el hilo que me sugieres, por ahí hay a su vez otro hilo del "Linux Journal" con unos ejemplos interesantes, en particular llamaron mi atención dos: el 5 (server2way.pl) y el 7 (clientfork.pl)... a partir de los cuales me parece que puedo hacer lo que busco, en principio me he trazado como metas reproducir este sencillo ejemplo, hacer los ajustes del caso para que funcione de acuerdo con mis necesidades y luego hacer una GUI... pero claro, primero caminemos y luego volamos... así que primero reproducir el ejemplo...

Les he probado, pero no he conseguido que funcionen a pesar que he agregado un chomp() luego del <STDIN>; esta es la parte responsable de pasar la palabra que el cliente escribe al servidor y el servidor responde de acuerdo a un código establecido, si el cliente dice en la STDIN "HELLO", el servidor dice "HI", si dice "NAME" pues responderá en mi caso "LOCALHOST" y así... el asunto es que parece que no está pasándose la palabra bien al lado del servidor, al menos he visto que no entra al bucle
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while (defined($buf = <$new_sock>)) {
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
lo cual llama mi atención pues con otros servidores y clientes que he estado experimentando y tienen esa misma sintaxis no pasa lo mismo...

¿Qué crees que pase?

¡Muchas Gracias!

Como referencia aquí está el código del servidor (server2way.pl) tomado del "Linux Journal".

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
 #!/usr/bin/perl -w
# server2way.pl - a server that reads from
# and writes to a client
use strict;
use IO::Socket;
use Sys::Hostname;
my $sock = new IO::Socket::INET(
                   LocalHost => 'localhost',
                   LocalPort => 7890,
                   Proto     => 'tcp',
                   Listen    => SOMAXCONN,
                   Reuse     => 1);
$sock or die "no socket :$!";
STDOUT->autoflush(1);
my($new_sock, $buf);
while ($new_sock = $sock->accept()) {
    # got a client connection, so read
    # line by line until end-of-file
    while (defined($buf = <$new_sock>)) {
   # respond to client request using
   # a cleverly disguised switch
        # statement
           foreach ($buf) {
                    /^HELLO$/ and
                         print($new_sock "Hi\n"),
                         last;
                    /^NAME$/  and
                         print($new_sock hostname(),
                         "\n"),
                         last;
                   /^DATE$/  and
                         print($new_sock
                               scalar(localtime),
                         "\n"),
                         last;
               # default case:
               print $new_sock "DEFAULT\n";
            }
    }
    close $new_sock;
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Y del Cliente (clientfork.pl)

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
 #!/usr/bin/perl -w
# clientfork.pl - a client that forks to
# read from STDIN and write to a server
use strict;
use IO::Socket;
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
                   PeerAddr => $host,
                   PeerPort => $port,
                   Proto    => 'tcp');
$sock or die "no socket :$!";
$sock->autoflush(1);
my($in, $buf, $kid);
die "fork fail: $!" unless defined($kid = fork);
if ($kid) {
    # parent reads from STDIN, prints to socket
    while (defined($in = <STDIN>)) {
           
            # Aqui he agregado el chomp...
            chomp $in;
           
            print $sock $in;
    }
    # kill the child process
    kill(TERM => $kid);
} else {
    # child reads from socket, prints to STDOUT
    while (defined($buf = <$sock>)) {
            print $buf;
    }
    close $sock;
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
jc.morataya
Perlero nuevo
Perlero nuevo
 
Mensajes: 33
Registrado: 2008-02-28 09:30 @438

Publicidad

Notapor jc.morataya » 2009-06-15 14:35 @649

Gracias Explorer por tu inmediata respuesta, este será sin duda mi primer libro de redes para Perl,

Saludos,
jc.morataya
Perlero nuevo
Perlero nuevo
 
Mensajes: 33
Registrado: 2008-02-28 09:30 @438

Notapor explorer » 2009-06-15 15:17 @678

Pero es que creo que el chomp() no debes ponerlo en el cliente, sino en el servidor... si, desde el cliente, mandas un texto, el servidor no lo recibe hasta que recibe, además, un carácter de fin de línea.

El autoflush() está justo para enviar los datos de forma inmediata, pero en el servidor estás usando el operador diamante (<>) por lo que no terminará de recibir la línea hasta no recibir el carácter fin de línea.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor jc.morataya » 2009-06-16 09:59 @458

Hola Explorer y miembros de Perl en Español,

Hice un chomp() del lado del servidor pero aún no reconoce la entrada estándar desde el cliente, lo que hice fue probar algo como esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $in = "HELLO\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y efectivamente, haciendo de esta forma el retorno de carro, el servidor responde con un "Hi" de acuerdo con el código, por otro lado he intentado del lado del servidor esto:


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
 my $in;
    while (defined($buf = <$new_sock>)) {
    while (defined($in = <STDIN>)) {
            #print "$buf\n";
            print($new_sock "$in \n"),
    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y funciona muy bien, pasa todo lo de la entrada estándar al lado del cliente... ¡vamos bien!

Lo que me pregunto es porqué esto mismo no funciona del lado del cliente. Pareciera como que si no permitiera hacer el retorno de carro...

¿Qué creen que pase?

Muchas gracias.
jc.morataya
Perlero nuevo
Perlero nuevo
 
Mensajes: 33
Registrado: 2008-02-28 09:30 @438

Notapor creating021 » 2009-06-16 14:46 @657

jc.morataya escribiste:Hola Creating021,

Muchas gracias por el ejemplo, muy ilustrativo, pero creo que no me he dado a entender bien, lo que necesito es que el servidor pueda enviar mensajes a todos los clientes, que es lo que yo llamo comunicacion vertical descendente y los clientes puedan enviar mensajes al servidor que es lo que yo llamo comunicacion vertical ascendente, es decir no se necesita comunicacion entre clientes que es lo que yo llamo comunicación horizontal... me entiendes?

El ejmplo del código que puse supone hacer lo siguiente:
Un cliente se conecta al servidor, el cual hace fork.
Luego, otro cliente se conecta (y nuevamente, el servidor hace fork) el cual le dice al servidor que quiere "chatear" con el cliente 1, y el servidor le dice al cliente 1 "¡Hey, cliente 2 te quiere hablar!".

Pero lo que tu quieres hacer es mandarle el mensaje a todos los clientes... eso con un bucle, que no cambiaría mucho el programa, o con IO::Multiplex :) (en Perl Coockbook hay un ejemplo).
jc.morataya escribiste:estoy queriendo hacer algo con la entrada estándar <STDIN> o sea, el servidor envia los mensajes a los clientes y estos a su vez pueden responderlos sería una comunicación bidireccional descendente-ascendente... creo que esto se puede hacer dentro del forking, puedes ejemplificar como hacerlo?

Al hacer fork simplemente no puedes usar el STDIN, al menos no dentro de el while donde se hace el fork ya que éste lo que hace es duplicar parte del programa (y por eso usamos la opción reuse al crear el socket).

Por cierto, server2way.pl sólo hacepta un cliente por vez, y si usas fork, tienes que lidiar con los "hijos".
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor jc.morataya » 2009-06-17 11:13 @509

Hola creating021 y miembros Perl en Español,

Aunque sé que lo que busco hacer es bastante sencillo, no lo consigo...

Tienes razón, ese ejemplo solo permite que un usuario se conecte. ¿Puedes decirme cómo hago para permitir que más usuarios se conecten?

¡Gracias!
jc.morataya
Perlero nuevo
Perlero nuevo
 
Mensajes: 33
Registrado: 2008-02-28 09:30 @438

Notapor jc.morataya » 2009-06-18 09:36 @441

Gracias a todos por la ayuda!
jc.morataya
Perlero nuevo
Perlero nuevo
 
Mensajes: 33
Registrado: 2008-02-28 09:30 @438

Anterior

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron