• Publicidad

SOCKET para enviar un archivo

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

SOCKET cliente-servidor

Notapor jcarranza » 2010-04-20 15:07 @671

¡Hola!

Quiero hacer una comunicación cliente-servidor por sockets de tal forma que:

1. al conectarse el cliente se muestre un mensaje en el servidor de CLIENTE CONECTADO (esto ya lo he conseguido),

2. desde el cliente escribo una cadena de texto que envío al servidor para que lo procese y lo convierta a mayúsculas,

3. y el servidor envía al cliente la cadena en mayúsculas.

Y FALLO EN EL TERCER PUNTO.

¿Cómo lo consigo? Tengo este código hecho:

SERVIDOR:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. #servidor
  4.  
  5. use IO::Socket;
  6. system ("title SERVIDOR");
  7.  
  8. $puerto = 9000;
  9. $protocolo="tcp";
  10.  
  11. $servidor = IO::Socket::INET->new(
  12.     Proto       => $protocolo,
  13.     LocalPort   => $puerto,
  14.     Listen      =>  1,
  15.     Reuse       =>  1,
  16. );
  17.  
  18. die "No puedo configurar el Servidor" unless $servidor;
  19.  
  20. system("cls");
  21. system ("color a");
  22.  
  23. print "\n";
  24. print scalar(localtime); print "\n\n";
  25. print "[Servidor INICIADO]\n\n";
  26. print "Puerto de comunicaciones: $puerto \n\n";
  27. print "Esperando conexiones remotas...\n\n";
  28. # $|++;
  29.  
  30. while( $remoto = $servidor->accept() ) #se mantiene a la espera de conexiones cliente
  31. {
  32.     $remoto->autoflush(1);
  33.         #activar el autoflush(), para que el envío de mensajes sea por cada línea, y no por bloques.
  34.     print "\nNuevo Cliente conectado!\n";
  35.  
  36.     while($datos_cliente = <$remoto> )
  37.         {
  38.                 print "Cadena recibida: $datos_cliente";
  39.                 print "Cadena transformada por el servidor: ";
  40.                 $datos_cliente=uc($datos_cliente);
  41.                 print $datos_cliente; print "\n\n";
  42.     }
  43. }
  44.  
  45. close $servidor;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


CLIENTE
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2. #CLIENTE MUY SENCILLO
  3.  
  4. use IO::Socket;
  5. system ("title CLIENTE");
  6.  
  7. $puerto = 9000;
  8. $protocolo="tcp";
  9.  
  10. $cliente = IO::Socket::INET->new(
  11.     Proto       => $protocolo,
  12.     PeerAddr    => "localhost",
  13.     PeerPort    =>  $puerto,
  14.     Reuse       =>  1,
  15. );
  16.  
  17. die "problema" unless $cliente;
  18.  
  19. system ("cls");
  20.  
  21. print scalar(localtime); print "\n\n";
  22. print "[Cliente INICIADO]\n\n";
  23. print "Puerto de comunicaciones: $puerto \n\n";
  24.  
  25.  
  26. print "Introduce un texto para enviar: ";
  27. $mensaje = <STDIN>;
  28. print $cliente $mensaje; #envío el mensaje al servidor a través del socket abierto.
  29.  
  30. close $cliente or die "close: $!";
  31.  
  32. print "\nSOCKET Cerrado\n";
  33. print "Pulse INTRO para continuar";
  34. $nada=<STDIN>;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
jcarranza
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2010-04-20 05:00 @250

Publicidad

Re: SOCKET cliente-servidor

Notapor explorer » 2010-04-20 17:04 @752

El servidor solo tiene que enviar la respuesta al cliente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         print $remoto $datos_cliente;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y en el cliente, recibirlo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $mensaje = <$cliente>;
  2. print "Respuesta: $mensaje";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Naturalmente, la comunicación es posible porque los mensajes son sencillos (son cadenas de texto terminadas en un carácter de fin de línea) y se leen y escriben de forma sencilla (con print() y con <>).
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

Re: SOCKET cliente-servidor

Notapor jcarranza » 2010-04-21 00:55 @080

Gracias, efectivamente, esto era lo que ponía pero en el sitio equivocado en el código del servidor... lo ponía fuera del bucle foreach().

Ahora funciona perfectamente.

En este mismo sentido, me gustaría que si le paso una cadena en minúsculas, el servidor me la devuelva en mayúsculas y si es una cadena en mayúsculas la que paso, que el servidor me la devuelva en minúsculas. ¿Cómo es esto?, ¿cómo sabe perl cuándo una cadena es en mayúsculas o en minúsculas y obrar en consecuencia?

¡¡Saludos!!
jcarranza
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2010-04-20 05:00 @250

Re: SOCKET cliente-servidor

Notapor explorer » 2010-04-21 05:00 @250

Perl no lo sabe. Es cuestión de saber antes en qué codificación estamos trabajando.

Tienes más información en perllocale, en concreto, donde hace referencia a la categoría LC_CTYPE.

Con el módulo POSIX, tienes dos funciones que te dicen si un carácter o cadena está escrito en minúsculas o mayúsculas: islower() y isupper(), pero no funciona con caracteres Unicode con valor superior a 255. Se recomienda usar las expresiones regulares /[[:lower:]]/ y /[[:upper:]]/.

Creo recordar que hay algún módulo más en CPAN, que también pueda dar esta información.
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

SOCKET para enviar un archivo

Notapor jcarranza » 2010-04-21 16:03 @711

Hola,

anteriormente codifiqué un socket para enviar una cadena al servidor y que éste lo devolviera al cliente de una determinada forma. Y pensando un poco en esta potencialidad, ¿se puede enviar un archivo (PDF, txt, JPG) desde el cliente al servidor o viceversa? ¿Cómo sería el código?

¡¡Saludos!!
jcarranza
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2010-04-20 05:00 @250

Re: SOCKET para enviar un archivo

Notapor creating021 » 2010-04-21 18:47 @824

¡Claro qué se puede!


¿Cómo sería el código?

Creo que es obvio que eso depende del protocolo o sistema de envío y recepción que estás usando.

Aquí hay un servidor "semihttp" con unos cuantos bugs :roll: como ejemplo de que es posible, de hecho puedes implementar cualquier protocolo de comunicaciones usando sockets, es más ya existe algunos programas en Perl que hacen justamente eso:
Sólo mira esta lista :wink:
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

Re: SOCKET para enviar un archivo

Notapor jcarranza » 2010-04-22 01:20 @097

¿Y cuál sería el código para enviar un PDF desde el cliente?

Hola,
estoy programando un sencillo socket cliente-servidor de tal forma que al conectarse el cliente en el servidor aparece el mensaje 'Nuevo cliente conectado'. El cliente, a su vez, recibirá un mensaje de que se ha conectado al servidor.

¿Cómo puedo programarlo de tal forma que el servidor no deje de ejecutarse (no salga a MSDOS) en espera de otros clientes? El cliente preguntará si se quiere abandonar o seguir conectado. Aquí les dejo el código que tengo: he sustituido WHILE por IF en el bucle del servidor ya que sino el cliente se quedaba bloqueado y no recibía el mensaje enviado por el servidor.

De momento tengo implementado el socket básico:

SERVIDOR
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. #servidor
  4.  
  5. use IO::Socket;
  6. system ("title SERVIDOR 4.1a");
  7.  
  8. $puerto = 9000;
  9. $protocolo="tcp";
  10.  
  11. $servidor = IO::Socket::INET->new(
  12.     Proto       => $protocolo,
  13.     LocalPort   => $puerto,
  14.     Listen      =>  1,
  15.     Reuse       =>  1,
  16. );
  17.  
  18. die "No puedo configurar el Servidor" unless $servidor;
  19.  
  20. system("cls");
  21. system ("color a");
  22.  
  23. print "\n";
  24. print scalar(localtime); print "\n\n";
  25. print "[Servidor INICIADO]\n\n";
  26. print "Puerto de comunicaciones: $puerto \n\n";
  27. print "Esperando conexiones remotas...\n\n";
  28. # $|++;
  29.  
  30.  
  31. $mensaje="Conexión establecida con el servidor!!";
  32.  
  33. while ($remoto = $servidor->accept() ) #se mantiene a la espera de conexiones cliente
  34. {
  35.     $remoto->autoflush(1);
  36.         #activar el autoflush(), para que el envío de mensajes sea por cada línea, y no por bloques.
  37.        
  38.         #para cada conexión entrante muestro en el servidor un mensaje y envío un comunicado al cliente
  39.     print "\nNuevo Cliente conectado!\n";
  40.         print $remoto $mensaje;
  41. }
  42.  
  43.  
  44. close $servidor;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



CLIENTE
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2. #CLIENTE MUY SENCILLO
  3.  
  4. use IO::Socket;
  5. system ("title CLIENTE 4.1a");
  6.  
  7. $contador=0;
  8. $puerto = 9000;
  9. $protocolo="tcp";
  10.  
  11. $cliente = IO::Socket::INET->new(
  12.     Proto       => $protocolo,
  13.     PeerAddr    => "localhost",
  14.     PeerPort    =>  $puerto,
  15.     Reuse       =>  1,
  16.  
  17. );
  18.  
  19. die "problema" unless $cliente;
  20.  
  21. system ("cls");
  22.  
  23. print scalar(localtime); print "\n\n";
  24. print "[Cliente INICIADO]\n\n";
  25. print "Puerto de comunicaciones: $puerto \n\n";
  26.  
  27. $|++; #La caché está activada por defecto. Para quitarla, basta con hacer $|++
  28.  
  29.  
  30. #recibiendo el mensaje del servidor y lo muestro en pantalla
  31. $mensaje = <$cliente>;
  32. print "$mensaje";  #mostrandolo en pantalla
  33. print "\n";
  34.  
  35.  
  36.  
  37. while ($contador==0)
  38. {
  39.         print "Desea salir (S/N)?: ";
  40.         $salida= <STDIN>;
  41.         chop($salida);
  42.  
  43.         if ($salida eq "S" or $salida eq "s")
  44.         {
  45.                 $contador=1;
  46.                 print "Ha decidido cerrar la comunicacion: \n";
  47.                 close $cliente or die "close: $!";
  48.                 print "\nSOCKET Cerrado\n";
  49.                 print "Pulse INTRO para continuar";
  50.                 $nada=<STDIN>;
  51.                 exit;
  52.         }
  53.        
  54.         else
  55.         {
  56.                 $contador=0;
  57.                 print "OK. Sigue conectado al servidor \n";
  58.                
  59.         }
  60.  
  61. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
jcarranza
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2010-04-20 05:00 @250

Re: SOCKET para enviar un archivo

Notapor explorer » 2010-04-22 02:52 @161

Pero... ¿es obligatorio usar IO::Socket?

Estoy con creating021: es mejor usar un servidor ya hecho. Por ejemplo, para el intercambio de ficheros, puedes usar Net::FTPServer en el lado del servidor, y luego, en el lado del cliente, puedes usar cualquier cliente de FTP.

Si lo que quieres es aprender a manejar IO::Socket, primero debes leerte la página dedicada a ello, aunque un poco antigua. Ahí encontrarás clientes y servidores que se conectan de diversas formas. Algunas de ellas incluyen las opciones de reutilizar las conexiones en bucles, que es lo que responde a tu segunda pregunta, pero yo creo que ya lo tienes hecho.

Mira, estos son dos ejemplos muy sencillos. El servidor está siempre funcionando, mientras que el cliente cierra en cuanto transmite la cadena.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use IO::Socket;
  4.  
  5. my $server = IO::Socket::INET->new(
  6.     Proto       => 'tcp',
  7.     LocalPort   =>  5800,
  8.     Listen      =>  1,
  9.     Reuse       =>  1,
  10. );
  11.  
  12. die "No puedo configurar servidor" unless $server;
  13. print "Server $0 aceptando clientes...\n";
  14.  
  15. $|++;
  16.  
  17. while( $cliente = $server->accept() ) {
  18.     $cliente->autoflush(1);
  19.     print "Cliente Conectado\n";
  20.     while(  defined( $line = <$cliente> )  ) {
  21.         print $line;
  22.     }
  23.     print "Cliente Desconectado\n";
  24.     close $cliente;
  25. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use IO::Socket;
  4.  
  5. $sock = IO::Socket::INET->new(
  6.     PeerAddr    => "localhost",
  7.     PeerPort    =>  5800,
  8.     Proto       => 'tcp',
  9.     Timeout     =>  1,
  10. );
  11. die "problema" unless $sock;
  12.  
  13. print "Introduce texto para mandar: ";
  14. $msg = <STDIN>;
  15. print $sock $msg;
  16. close $sock;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Para el intercambio de ficheros, en lugar de usar print(), deberás cambiar el modo de transmisión a binario con binmode(), y luego usar syswrite() sobre el canal. En el lado del cliente, al revés, usar sysread().

Actualización: aquí hay unos ejemplos para transmitir un fichero.
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. $|++;
  8.  
  9. my $server = IO::Socket::INET->new(
  10.     Proto       => 'tcp',
  11.     LocalPort   =>  5800,
  12.     Listen      =>  1,
  13.     Reuse       =>  1,
  14. );
  15.  
  16. die "No puedo configurar servidor" unless $server;
  17. print "Servidor $0 aceptando clientes...\n";
  18.  
  19. while( my $cliente = $server->accept() ) {
  20.  
  21.     $cliente->autoflush(1);
  22.  
  23.     print "Cliente conectado. Esperamos nombre de fichero\n";
  24.  
  25.     my    $fichero = <$cliente>;
  26.     chomp $fichero;
  27.  
  28.     if (! -e $fichero) {
  29.         print $cliente "ERROR: no encuentro ese fichero\n";
  30.         next;
  31.     }
  32.  
  33.     print $cliente "Ok\n";
  34.  
  35.     my $largo = -s $fichero;
  36.  
  37.     print "Transmitiendo fichero $fichero al cliente ($largo bytes)\n";
  38.  
  39.     open my $FICHERO, q[<], $fichero  or next;  # Abrimos el fichero
  40.     binmode $FICHERO;
  41.     sysread $FICHERO, my($buffer), $largo;      # y lo leemos
  42.     close   $FICHERO;
  43.  
  44.     binmode  $cliente;
  45.     syswrite $cliente, $buffer, $largo;         # y lo enviamos
  46. }
  47. continue {
  48.     print "Cliente desconectado\n";
  49.  
  50.     close $cliente;
  51. }
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 strict;
  3. use warnings;
  4.  
  5. use IO::Socket;
  6.  
  7. $|=1;
  8.  
  9. my $sock = IO::Socket::INET->new(
  10.     PeerAddr    => "localhost",
  11.     PeerPort    =>  5800,
  12.     Proto       => 'tcp',
  13.     Timeout     =>  1,
  14. );
  15. die 'Problema en la conexión' unless $sock;
  16.  
  17. print "Introduce fichero a leer: ";
  18.  
  19. my    $fichero = <STDIN>;
  20. chomp $fichero;
  21.  
  22. print $sock "$fichero\n";
  23.  
  24. my    $respuesta = <$sock>;
  25. print $respuesta;
  26. chomp $respuesta;
  27.  
  28. if ($respuesta eq 'Ok') {
  29.  
  30.     binmode $sock;
  31.  
  32.     open my $FICHERO, q[>], "$fichero.new" or die "ERROR: No puedo escribir el fichero\n";
  33.     binmode $FICHERO;
  34.  
  35.     while (sysread $sock, my $buffer, 10000) {       # vamos leyendo en bloques de 10k
  36.         print $FICHERO $buffer;
  37.         print '.';
  38.     }
  39.  
  40.     print "\n";
  41.  
  42.     close  $FICHERO;
  43. }
  44.  
  45. close $sock;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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


Volver a Básico

¿Quién está conectado?

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