• Publicidad

Enviar datos sin cambiar formato por socket

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

Enviar datos sin cambiar formato por socket

Notapor hexbase » 2012-02-18 17:44 @781

Hola,

Tengo un servidor en Perl y un cliente de prueba en Perl.

Quiero enviar una cadena (string) sin enviarla línea por línea, respetando su formato original,
porque si lo envío como "print $socket $datos-ejemplo . "\n";", me llegan los datos por líneas.

Una duda, para enviar datos, ¿es necesario que la línea finalice con '\n'?
Porque sin '\n', parece ser que la línea no se envía.

Gracias a explorer por compartir el código de server/cliente usando sockets.

El código del servidor recibiendo los datos es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $|++;
  2.  
  3. while( $cliente = $server->accept() ) {
  4.     $cliente->autoflush(1);
  5.    
  6.     while(  defined( $line = <$cliente> )  ) {
  7.         print $line; #. "\n";
  8.         if ($line eq "Hello"){
  9.          print "sent\n";
  10.          print $cliente "client connected\n";
  11.       }
  12.       if ($line =~ m/(-----END RSA PUBLIC KEY-----)/i ){ #&& length ($line) == '425'
  13.          print "Key recibida\n";
  14.          $line = $client_pub_key;
  15.       }
  16.     }
  17.     close $cliente;
  18. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Y la porción de código del cliente :
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print $socket "Hello\n";
  2.   while(  defined( $line = <$socket> )  ) {
  3.                
  4.         if ($line eq "client connected")
  5.        {
  6.         print $socket $key . "\n";
  7.     }
  8.  
  9.   }
  10. $socket->close();
  11.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $datos_ejemplo = '-----BEGIN RSA PUBLIC KEY-----
  2. MIIBCgKCAQEAsI016S2GsM4yJ7bDxvwlj1zaO5uP/SWfhoZQu5gKQ7be7zvpfJ/4
  3. kqBRiN4WrCkr2KysE4MHa1Trnv0NFCLLAGuat+49sYyXosEUuJUfW13Xx/vhidxb
  4. jb/BzpxPY6tVtEv72o6zDzzYPtWx6NiAPrdNWRHCTw/+onCm/NEafA+JZbZI+UKW
  5. Iqv14786aohJFGfJTzrRG8kK5XAD944EPxERJk2R4JbZP/aGhvtnNb/vS7DKw86i
  6. y1dsH/C4Yv6s+djOB2yY7H2DQtImmrUouE1a63Awt2dowbq5J/Xfn5+B1uqs2yff
  7. PfrPsC2YogW3//Joi+f7fLRMQqWeSLWChQIDAQAB
  8. -----END RSA PUBLIC KEY-----';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Los datos llegan como:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. -----BEGIN RSA PUBLIC KEY-----MIIBCgKCAQEAsI016S2GsM4yJ7bDxvwlj1zaO5uP/SWfhoZQu5gKQ7be7zvpfJ/4kqBRiN4WrCkr2KysE4MHa1Trnv0NFCLLAGuat+49sYyXosEUuJUfW13Xx/vhidxbjb/BzpxPY6tVtEv72o6zDzzYPtWx6NiAPrdNWRHCTw/+onCm/NEafA+JZbZI+UKWIqv14786aohJFGfJTzrRG8kK5XAD944EPxERJk2R4JbZP/aGhvtnNb/vS7DKw86iy1dsH/C4Yv6s+djOB2yY7H2DQtImmrUouE1a63Awt2dowbq5J/Xfn5+B1uqs2yffPfrPsC2YogW3//Joi+f7fLRMQqWeSLWChQIDAQAB-----END RSA PUBLIC KEY-----
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Muchas gracias
hexbase
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2009-07-11 19:57 @873

Publicidad

Re: Enviar datos sin cambiar formato por socket

Notapor explorer » 2012-02-18 20:30 @895

¿El cliente y el servidor están en el mismo sistema operativo?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Enviar datos sin cambiar formato por socket

Notapor hexbase » 2012-02-19 19:44 @864

Si, y en la misma pc. No he seguido probando. Espero una favorable respuesta. :D
hexbase
Perlero nuevo
Perlero nuevo
 
Mensajes: 7
Registrado: 2009-07-11 19:57 @873

Re: Enviar datos sin cambiar formato por socket

Notapor explorer » 2012-02-19 21:34 @940

Hay algunos detalles que no quedan claros, como por ejemplo, en el servidor, no sabemos de dónde sale la variable $client_pub_key. Pero lo principal es que estamos enviando información que contiene caracteres de avance de línea, dentro de un protocolo entre servidor y cliente que precisamente usa los avance de línea para intercambiar comandos.

En la línea 6 del cliente estás enviando la firma, que es recogida, línea a línea, por el while() de la línea 6 del servidor. Te faltan las líneas de programa que vayan acumulando las líneas de la firma que vas recibiendo.

Aquí hay un ejemplo de lo que se puede hacer. Primero el servidor:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use IO::Socket;
  6.  
  7. my $sock = IO::Socket::INET->new(
  8.     LocalHost => 'localhost',             # Opcional. Indicamos en dónde escuchamos
  9.     LocalPort => 1234,                    # Por dónde
  10.     Listen    => 125,                     # Número de oyentes
  11.     Reuse     => 1,                       # Admitir nuevas peticiones de forma simultánea
  12.     Proto     => 'tcp',                   # Protocolo
  13. ) or die "Error creating socket: $!\n";
  14.  
  15. $|++;                                     # No caché en pantalla (autoflush)
  16.  
  17. print "-- Server Program --\n";
  18.  
  19. while (my $cliente = $sock->accept() ) {        # Esperamos conexiones
  20.     print "¡Conexión!\n";
  21.  
  22.     $cliente->autoflush(1);                     # Opcional
  23.  
  24.     my $key;
  25.  
  26.     while (defined(my $line = <$cliente>)) {    # Leemos por líneas
  27.         chomp $line;
  28.         print "Recibido: [$line]\n";
  29.  
  30.         if ($line eq "Hello") {                 # Comienzo del protocolo
  31.            print $cliente "client connected\n"; # Respondemos
  32.         }
  33.  
  34.         if ($line =~ m/-----BEGIN RSA PUBLIC KEY-----/i .. $line =~ m/-----END RSA PUBLIC KEY-----/i) {
  35.             $key .= "$line\n";                  # es necesario un "\n" porque se lo hemos quitado antes
  36.         }
  37.     }
  38.  
  39.     print "Fin de Conexión\n";
  40.     close $cliente;
  41.  
  42.     chomp $key;                                 # quitamos el último "\n" sobrante
  43.     print "Key: [$key]\n";
  44. }
  45.  
  46. close($sock);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Arrancamos y quedamos esperando una conexión por parte del cliente. Cuando lo hace, leemos lo que nos manda, por líneas. Si nos manda una línea 'Hello', entonces respondemos con el mensaje de que estamos conectados. Si no, miramos a ver si la línea entra dentro del rango de una firma RSA, y si es así, la vamos agregando a $key. Finalmente, cuando el cliente corta la conexión, imprimimos la firma recibida.

Este es el cliente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use IO::Socket;
  6.  
  7. my $socket = IO::Socket::INET->new(
  8.     PeerAddr => 'localhost',                # A dónde hay que conectarse
  9.     PeerPort => 1234,                       # y en qué puerto
  10.     Proto    => 'tcp',                      # y con qué protocolo
  11.     Timeout  => 30,                         # tiempo máximo de espera de conexión
  12. ) or die "Error creating socket: $!\n";
  13.  
  14. my $key = '-----BEGIN RSA PUBLIC KEY-----
  15. MIIBCgKCAQEAsI016S2GsM4yJ7bDxvwlj1zaO5uP/SWfhoZQu5gKQ7be7zvpfJ/4
  16. kqBRiN4WrCkr2KysE4MHa1Trnv0NFCLLAGuat+49sYyXosEUuJUfW13Xx/vhidxb
  17. jb/BzpxPY6tVtEv72o6zDzzYPtWx6NiAPrdNWRHCTw/+onCm/NEafA+JZbZI+UKW
  18. Iqv14786aohJFGfJTzrRG8kK5XAD944EPxERJk2R4JbZP/aGhvtnNb/vS7DKw86i
  19. y1dsH/C4Yv6s+djOB2yY7H2DQtImmrUouE1a63Awt2dowbq5J/Xfn5+B1uqs2yff
  20. PfrPsC2YogW3//Joi+f7fLRMQqWeSLWChQIDAQAB
  21. -----END RSA PUBLIC KEY-----';
  22.  
  23. print "$key\n";
  24.  
  25. print $socket "Hello\n";
  26.  
  27. my $line = <$socket>;
  28. chomp $line;
  29.  
  30. if ( $line eq "client connected" ) {            # podemos comparar porque hemos quitado el "\n"
  31.     print $socket $key . "\n";                  # agregamos "\n" porque la $key no lo tiene
  32. }
  33.  
  34. $socket->close();
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Es muy sencillo: nos conectamos al servidor, le mandamos el 'Hello', leemos la siguiente línea que nos responda, y si es lo acordado, le enviamos toda la $key.

Esta es otra variación, en la que modificamos el protocolo, para decirle al servidor exactamente cuántos bytes vamos a enviarle (la longitud de la firma).
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use IO::Socket;
  6.  
  7. my $sock = IO::Socket::INET->new(
  8.     LocalHost => 'localhost',             # Opcional. Indicamos en dónde escuchamos
  9.     LocalPort => 1234,                    # Por dónde
  10.     Listen    => 125,                     # Número de oyentes
  11.     Reuse     => 1,                       # Admitir nuevas peticiones de forma simultánea
  12.     Proto     => 'tcp',                   # Protocolo
  13. ) or die "Error creating socket: $!\n";
  14.  
  15. $|++;                                     # No caché en pantalla (autoflush)
  16.  
  17. print "-- Server Program --\n";
  18.  
  19. while (my $cliente = $sock->accept() ) {        # Esperamos conexiones
  20.     print "¡Conexión!\n";
  21.  
  22.     $cliente->autoflush(1);                     # Opcional
  23.  
  24.     my $key;
  25.  
  26.     while (defined(my $line = <$cliente>)) {    # Leemos por líneas
  27.         chomp $line;
  28.  
  29.         print "Recibido: [$line]\n";
  30.  
  31.         if ($line =~ /RSA(\d+)/) {              # Cabecera del protocolo
  32.  
  33.             my $n = read($cliente, $key, $1);   # Leemos exactamente esa cantidad de bytes
  34.  
  35.             print "Fin de Conexión. $n bytes leídos\n";
  36.             close $cliente;                     # y cerramos
  37.  
  38.             print "Key: [$key]\n";
  39.  
  40.             last;
  41.         }
  42.     }
  43. }
  44.  
  45. close($sock);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
El cliente también lo modificamos un poco:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use IO::Socket;
  6.  
  7. my $socket = IO::Socket::INET->new(
  8.     PeerAddr => 'localhost',                # A dónde hay que conectarse
  9.     PeerPort => 1234,                       # y en qué puerto
  10.     Proto    => 'tcp',                      # y con qué protocolo
  11.     Timeout  => 30,                         # tiempo máximo de espera de conexión
  12. ) or die "Error creating socket: $!\n";
  13.  
  14. my $key = '-----BEGIN RSA PUBLIC KEY-----
  15. MIIBCgKCAQEAsI016S2GsM4yJ7bDxvwlj1zaO5uP/SWfhoZQu5gKQ7be7zvpfJ/4
  16. kqBRiN4WrCkr2KysE4MHa1Trnv0NFCLLAGuat+49sYyXosEUuJUfW13Xx/vhidxb
  17. jb/BzpxPY6tVtEv72o6zDzzYPtWx6NiAPrdNWRHCTw/+onCm/NEafA+JZbZI+UKW
  18. Iqv14786aohJFGfJTzrRG8kK5XAD944EPxERJk2R4JbZP/aGhvtnNb/vS7DKw86i
  19. y1dsH/C4Yv6s+djOB2yY7H2DQtImmrUouE1a63Awt2dowbq5J/Xfn5+B1uqs2yff
  20. PfrPsC2YogW3//Joi+f7fLRMQqWeSLWChQIDAQAB
  21. -----END RSA PUBLIC KEY-----';
  22.  
  23. my $msg = 'RSA' . length $key;
  24.  
  25. print $socket "$msg\n$key";     # Mandamos cabecera y mensaje
  26.  
  27. $socket->close();
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
En definitiva, tú eres el que puede definir el protocolo a usar. Y según sea, necesitarás usar los "\n", o no.

Finalmente, esta es otra versión, con código superabreviado, cortesía del (monstruoso) módulo IO::All
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use IO::All;
  4.  
  5. say '-- Server Program --';
  6.  
  7. my $socket = io(':1234')->fork->accept;
  8.  
  9. say '¡Conexión!';
  10.  
  11. my $header = $socket->getline;
  12.  
  13. if ($header =~ /RSA(\d+)/) {                    # Comienzo del protocolo
  14.  
  15.     my $n = $socket->read($key, $1);
  16.    
  17.     say "$n bytes leídos.";
  18.     say "Key: [$key]";
  19. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use IO::All;
  3.  
  4. my $io = io(':1234');
  5.  
  6. my $key = '-----BEGIN RSA PUBLIC KEY-----
  7. MIIBCgKCAQEAsI016S2GsM4yJ7bDxvwlj1zaO5uP/SWfhoZQu5gKQ7be7zvpfJ/4
  8. kqBRiN4WrCkr2KysE4MHa1Trnv0NFCLLAGuat+49sYyXosEUuJUfW13Xx/vhidxb
  9. jb/BzpxPY6tVtEv72o6zDzzYPtWx6NiAPrdNWRHCTw/+onCm/NEafA+JZbZI+UKW
  10. Iqv14786aohJFGfJTzrRG8kK5XAD944EPxERJk2R4JbZP/aGhvtnNb/vS7DKw86i
  11. y1dsH/C4Yv6s+djOB2yY7H2DQtImmrUouE1a63Awt2dowbq5J/Xfn5+B1uqs2yff
  12. PfrPsC2YogW3//Joi+f7fLRMQqWeSLWChQIDAQAB
  13. -----END RSA PUBLIC KEY-----';
  14.  
  15. my $msg = 'RSA' . length $key;
  16.  
  17. $io->print("$msg\n$key");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En vez de usar print() y read(), se pueden usar las funciones send() y recv(), para tener mayor control sobre lo que se envía y recibe y cómo se envía y recibe.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 27 invitados