• Publicidad

Paso de comandos a través de un socket

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

Paso de comandos a través de un socket

Notapor jcarranza » 2010-04-26 08:23 @391

Hola, me gustaría hacer una comunicación cliente-servidor para que desde el cliente se pasen comandos al servidor (fecha, usuarios, salir). En concreto:

1. Los comandos permitidos son:
fecha: Muestra la fecha y hora actual del servidor
usuarios: Muestra los usuarios activos del sistema (asumiremos
2. que el servidor se ejecuta en un sistema compatible con UNIX y
que posee el comando who).

* La comunicación se llevará a cabo de la siguiente manera (cada envío,
del servidor o del cliente, finalizará con un salto de línea):
+ Al recibir la conexión del cliente, el servidor enviará el mensaje
"Bienvenido.".
+ El cliente enviará el comando deseado ("fecha" o "usuarios").
+ En caso de tratarse de un comando válido, el servidor responderá
con "OK" seguido del resultado de la ejecución del mismo (el cual
puede constar de varias líneas) y luego el mensaje "FIN".
+ En caso de recibir un comando erróneo, el servidor responderá
con el mensaje "ERR".
+ En cualquier caso, el servidor volverá a esperar otro comando.
+ Si el cliente envía el comando "salir" el servidor responderá con
el mensaje de despedida "Adiós." y cerrará la conexión.

La conexión puede ser cerrada por el cliente en cualquier momento, sin que esto afecte el estado del servidor.

De momento he programado esto pero me he hecho un lío con tantas modificaciones que he hecho y por ello ¡¡solicito ayuda!!

SERVIDOR
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use IO::Socket;
  4. $|++;
  5. require "mis_funciones.pl";
  6.  
  7.  
  8.  system("cls");
  9.  system ("title SERVIDOR 5.1");
  10.  
  11.  
  12. $puerto = 2222;
  13. $protocolo='tcp';
  14.  
  15. $servidor = IO::Socket::INET->new(Proto    =>$protocolo,
  16.                                   LocalPort=>$puerto,
  17.                                   Listen   =>SOMAXCONN,
  18.                                   Reuse    =>1)
  19.             or die "Error al iniciar el servidor";
  20.  
  21.  
  22.                        
  23. system ("color a");
  24. print "\n";
  25. print scalar(localtime); print "\n\n";
  26. print "[Servidor INICIADO] --> ";
  27. print "Puerto de comunicaciones: $puerto \n\n";
  28. print "->Esperando conexiones...\n\n";
  29.  
  30. while ($conexion = $servidor->accept())
  31. {
  32.         $ip = $conexion->peerhost;
  33.         print "[Conexion establecida desde $ip]\n";
  34.         print $conexion "SERVIDOR: Bienvenido.\n"; #mensaje de bienvenida que envío al cliente
  35.        
  36.     do
  37.         {
  38.         if ($comando = <$conexion>) #si el cliente ha introducido un comando
  39.                 {
  40.             $comando =~ s/\r\n|\n//g; #elimino el fin de línea al final de la cadena leída
  41.                         ejecutar($comando, $conexion);
  42.         }
  43.                 else
  44.                 {
  45.             $comando = 'salir';
  46.         }
  47.     }
  48.         until ($comando eq 'salir');
  49.        
  50.        
  51.     $conexion->shutdown(2);
  52.     print "[Conexion finalizada desde $ip]\n\n";
  53. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4





MIS_FUNCIONES
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub ejecutar($$)
  2. {
  3.         #capturamos las variables llamadas
  4.         $comando =shift;
  5.         $conexion =shift;
  6.         #inicializamos la variable resultado
  7.         $resultado = '';
  8.        
  9.        
  10.         if ($comando eq 'fecha')
  11.                 { $resultado = localtime() . "\n";}
  12.                
  13.         elsif ($comando eq 'usuarios')
  14.                 { $resultado = 'who' . "\n";}
  15.                
  16.         elsif ($comando eq 'salir')
  17.                 { $resultado= "Gracias por usar este servicio. Adiós.\n";}
  18.                
  19.         else
  20.         {
  21.         print $conexion "ERR\n";
  22.     }
  23.        
  24.        
  25.        
  26.     if ($resultado)
  27.         {
  28.         print "Valor de resultado= $resultado \n";
  29.         print $conexion "OK\n";
  30.         print $conexion $resultado;
  31.         print $conexion "FIN\n";
  32.     }
  33.        
  34.  
  35. }
  36. 1;
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.  
  3. use IO::Socket;
  4.  
  5. $servidor='localhost';
  6. $puerto=2222;
  7.  
  8. system("cls");
  9. system("title CLIENTE 5.1");
  10.  
  11.  
  12. $conexion = new IO::Socket::INET(PeerAddr => $servidor,
  13.                                  PeerPort => $puerto,
  14.                                  Proto => 'tcp')
  15.  
  16. or die "Error al conectar con el SERVIDOR $servidor \n";
  17.  
  18.  
  19. #mensaje que captura el cliente enviado por el servidor
  20. $mensaje = <$conexion>;
  21. print "$mensaje";
  22. print "\n";
  23.  
  24.  
  25. print "Introduce el comando: ";
  26. $comando=<STDIN>;
  27.  
  28.  
  29. $estado = <$conexion>;
  30. print "$estado \n";
  31.  
  32. if ($estado eq "OK\n") {
  33.     $salida = <$conexion>;
  34.     while ($salida ne "FIN\n") {
  35.         print $salida;
  36.         $salida = <$conexion>;
  37.     }
  38. } elsif ($estado eq "ERR\n") {
  39.     print "Comando no valido\n";
  40. } else {
  41.     print "Error en el servidor\n";
  42. }
  43. print $conexion "salir\n";
  44.  
  45. $mensaje = <$conexion>;
  46. $conexion->shutdown(2);
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: Paso de comandos a través de un socket

Notapor explorer » 2010-04-26 15:27 @685

En el hilo que tu mismo abriste, llamado "SOCKET para enviar un archivo", te puse un enlace a una página de LinuxJournal (mensaje del día 2010-04-22 09:52 CET @452), donde repasa el funcionamiento de Socket en Perl.

Vienen varios ejemplos. En el apartado Bidirectional Communication, se comenta el ejemplo de un servidor que responde a los comandos enviados desde un cliente. En el listado 5 tienes el servidor, y en el listado 6, el cliente.

Viendo tu código por encima, creo que estás muy cerca.
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: Paso de comandos a través de un socket

Notapor jcarranza » 2010-04-27 01:04 @086

¡Hola!
He estado todo el día de ayer con esto y nada, que no me sale. He leído la web que me recomendaste pero sigue fallándome.

Mira a ver si echas un vistazo al código y a ver si es posible que me aportes una solución. ¡¡¡¡Espero con impaciencia!!!!

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

Re: Paso de comandos a través de un socket

Notapor explorer » 2010-04-27 02:58 @165

No he visto que hayas cambiado el código.

Recuerda que puedes editar tus propios mensajes, pulsando en el botón que aparece en el mensaje, abajo a la derecha, donde pone "Editar mensaje".

Pones el nuevo código, y vemos lo que llevas hecho hasta ahora.

Otra forma, es empezar con los listados que te he indicado, ya que funcionan muy bien.

No lo he visto en profundidad, pero parece que hay un problema en el orden de los mensajes en que se intercambian el servidor y el cliente.
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: Paso de comandos a través de un socket

Notapor jcarranza » 2010-04-28 03:55 @205

¡¡Hola, explorer!!

¿Y cómo lo codificarías correctamente bajo tu punto de vista?
¡¡Este script lo he viciado de tantos cambios aquí y allá!!

¡¡¡Saludos!!!
Última edición por explorer el 2010-04-28 04:34 @232, editado 1 vez en total
Razón: ¡¡¡
jcarranza
Perlero nuevo
Perlero nuevo
 
Mensajes: 44
Registrado: 2010-04-20 05:00 @250

Re: Paso de comandos a través de un socket

Notapor jcarranza » 2010-04-29 02:19 @138

Hola, creo que he avanzado algo. Sin embargo, no sale como a mí me gustaría:

1. quiero que al introducir un comando válido desde el cliente que aparezca la respuesta así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
               OK
               <<la respuesta>>
               FIN
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

pero el FIN no me aparece y eso que se lo paso al socket.

2. me gustaría ir insertando comandos en el cliente y que no se saliera a la consola hasta que no se introduzca el comando 'salir'.

Aquí dejo el código que he programado hasta ahora:

SERVIDOR
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use IO::Socket;
  4. $|++;
  5. require "mis_funciones.pl";
  6. use Sys::Hostname;
  7.  
  8.  system("cls");
  9.  system ("title SERVIDOR 5.1");
  10.  
  11.  
  12. $puerto = 2222;
  13. $protocolo='tcp';
  14.  
  15. $servidor = IO::Socket::INET->new(Proto    =>$protocolo,
  16.                                   LocalPort=>$puerto,
  17.                                   Listen   =>SOMAXCONN,
  18.                                   Reuse    =>1)
  19.             or die "Error al iniciar el servidor";
  20.  
  21.  
  22.                        
  23. system ("color a");
  24. print "\n";
  25. print scalar(localtime); print "\n\n";
  26. print "[Servidor INICIADO] --> ";
  27. print "Puerto de comunicaciones: $puerto \n\n";
  28. print "->Esperando conexiones...\n\n";
  29.  
  30. while ($conexion = $servidor->accept())
  31. {
  32.         $ip = $conexion->peerhost;
  33.         print "[Conexion establecida desde $ip]\n";
  34.         print $conexion "SERVIDOR: Bienvenido "; print $conexion hostname() . "\n"; #mensaje de bienvenida que envío al cliente
  35.        
  36.     do
  37.         {
  38.         if ($comando = <$conexion>) #si el cliente ha introducido un comando y lo captura el servidor
  39.                 {
  40.             $comando =~ s/\r\n|\n//g; #elimino el fin de línea al final de la cadena leída
  41.                         ejecutar($comando, $conexion);
  42.         }
  43.                 else
  44.                 {
  45.             $comando = 'salir';
  46.         }
  47.     }
  48.         until ($comando eq 'salir');
  49.        
  50.        
  51.     $conexion->shutdown(2);
  52.     print "[Conexion finalizada desde $ip]\n\n";
  53. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4





MIS-FUNCIONES
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub ejecutar($$)
  2. {
  3.         #capturamos las variables llamadas
  4.         $comando =shift;
  5.         $conexion =shift;
  6.         #inicializamos la variable resultado
  7.         $resultado;
  8.        
  9.        
  10.         if ($comando eq 'fecha')
  11.                 { $resultado = localtime() . "\n";}
  12.                
  13.         elsif ($comando eq 'usuarios')
  14.                 { $resultado = 'who' . "\n";}
  15.                
  16.         elsif ($comando eq 'salir')
  17.                 { $resultado= "Gracias por usar este servicio. Adios.\n";}
  18.                
  19.         else
  20.         {
  21.         print $conexion "ERROR\n";
  22.     }
  23.        
  24.        
  25.        
  26.     if ($resultado)
  27.         {
  28.  
  29.                 print $conexion "OK\n";
  30.                 print $conexion $resultado;
  31.                 print $conexion "\nFIN\n";
  32.     }
  33.        
  34.  
  35. }
  36. return 1;
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.  
  3. use IO::Socket;
  4.  
  5.  
  6. $servidor='localhost';
  7. $puerto=2222;
  8.  
  9. system("cls");
  10. system("title CLIENTE 5.1");
  11.  
  12.  
  13.  
  14. $conexion = new IO::Socket::INET(PeerAddr => $servidor,
  15.                                  PeerPort => $puerto,
  16.                                  Proto => 'tcp')
  17.  
  18. or die "Error al conectar con el SERVIDOR $servidor \n";
  19.  
  20.  
  21. #mensaje que captura el cliente enviado por el servidor
  22. $mensaje = <$conexion>;
  23. print "$mensaje";
  24. print "\n";
  25.  
  26.  
  27. print "Introduce el comando: ";
  28. $comando=<STDIN>;
  29. print $conexion $comando;
  30.  
  31.  
  32. $estado = <$conexion>;
  33. print "$estado \n";
  34.  
  35. if ($estado eq "OK\n")
  36. {
  37.     $salida = <$conexion>;
  38.     while ($salida ne "FIN\n")
  39.         {
  40.         print $salida;
  41.         $salida = <$conexion>;
  42.     }
  43.        
  44. }
  45.  
  46. elsif ($estado eq "ERROR\n")
  47. {
  48.     print "Este Comando no es valido\n";
  49. }
  50.  
  51. else
  52. {
  53.     print "Error en el servidor\n";
  54. }
  55.  
  56. print $conexion "salir\n";
  57.  
  58. $mensaje = <$conexion>;
  59. $conexion->shutdown(2);
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

Re: Paso de comandos a través de un socket

Notapor explorer » 2010-04-29 05:56 @289

Pero si no es tan complicado... es cuestión de seguir, una a una, las líneas de los listados que te he indicado...

Cliente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use strict;
  4. use warnings;
  5.  
  6. use IO::Socket;
  7.  
  8. my $sock = IO::Socket::INET->new(
  9.     PeerAddr    => "localhost",
  10.     PeerPort    =>  5800,
  11.     Proto       => 'tcp',
  12.     Timeout     =>  1,
  13. ) or
  14.     die "Problema al crear la conexión. $!";
  15.  
  16. STDOUT->autoflush(1);
  17. $sock ->autoflush(1); # No es necesario porque está activo por defecto
  18.  
  19. while ($sock->connected) {
  20.  
  21.     print "Comando: ";
  22.     my $comando = <STDIN>;
  23.  
  24.     print $sock $comando;               # comando
  25.  
  26.     print scalar <$sock>;               # respuesta
  27.  
  28.     last if $comando =~ /salir/;
  29.  
  30. }
  31.  
  32. close $sock;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Servidor:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use strict;
  4. use warnings;
  5.  
  6. use IO::Socket;
  7.  
  8.  
  9. # Crear servidor
  10. my $servidor = IO::Socket::INET->new(
  11.     Proto       => 'tcp',
  12.     LocalPort   =>  5800,
  13.     Listen      =>  1,
  14.     Reuse       =>  1,
  15. ) or
  16.     die "No puedo configurar servidor. $!";
  17.  
  18. say "Servidor $0 aceptando clientes...";
  19.  
  20. # No caché en salida
  21. STDOUT->autoflush(1);
  22. $servidor->autoflush(1);
  23.  
  24. # Bucle sin fin
  25. while (my $conexion = $servidor->accept()) {
  26.     say 'Cliente conectado. Esperando comandos.';
  27.  
  28.     while (defined(my $comando = <$conexion>)) {
  29.         chomp $comando;
  30.  
  31.         say "Procesando [$comando]";
  32.  
  33.         my $respuesta = procesa($conexion, $comando);
  34.  
  35.         given ($respuesta) {
  36.             when ('salir') {
  37.                 say $conexion 'Fin de sesión';
  38.                 say           'Fin de sesión';
  39.                 last;
  40.             }
  41.             when ('error') {
  42.                 say $conexion "ERROR. Los comandos permitidos son 'fecha', 'usuarios' y 'salir'";
  43.             }
  44.             default {
  45.                 say $conexion $respuesta;
  46.             }
  47.         }
  48.     }
  49.  
  50.     say 'Cliente desconectado.';
  51.     close $conexion;
  52. }
  53.  
  54. sub procesa {
  55.     my ($conexion, $comando) = @_;
  56.  
  57.     given ($comando) {
  58.         when ('fecha') {
  59.             return scalar localtime;
  60.         }
  61.         when ('usuarios') {
  62.             # Componemos la lista de usuarios a partir de las líneas devueltas por 'who'
  63.             # que, justamente, es lo que hace el comando 'users'
  64.             return join q[ ], map { (split)[0] } qx(who);
  65.         }
  66.         when ('salir') {
  67.             return 'salir';
  68.         }
  69.         default {
  70.             return 'error';
  71.         }
  72.     }
  73. }
  74.  
Coloreado en 0.002 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

Re: Paso de comandos a través de un socket

Notapor jcarranza » 2010-04-30 03:09 @173

Gracias Explorer, tu ejemplo me ha servido para depurar mis errores.
No lo he hecho así pero me has ayudado sobresalientemente, sobre todo en la forma de ordenar los mensajes atendiendo al resultado que se procesa.

¡¡Y tu ejemplo va de fábula!!

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


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: Google [Bot] y 0 invitados