Página 1 de 1

Problema con sockets e hilos

NotaPublicado: 2008-09-20 22:46 @990
por eddycito
Hola qué tal, les comento que estoy haciendo un monitor de red, bueno el punto es que tengo un botón.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $activar_seg = Gtk2::ToggleToolButton->new_from_stock('gtk-dialog-authentication');
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
la cual llama a una función donde se crea un hilo y dentro del hilo se encuentra el socket.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$activar_seg->signal_connect (clicked => \&ActivaS);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
sub ActivaS{

    my $togg = shift;

    if ($togg->get_active) {

        $hilo_seg = threads->create(
            sub {
                $sock = new IO::Socket::INET (
                        LocalHost => 'localhost',
                        LocalPort => 1100,
                        Proto     => 'tcp',
                        Listen    =>  6,
                        Reuse     => 1
                );
                die "No se ha podido crear el socket: $!\n" unless $sock;
                print "-------------------------------------------------\n";
                print "-         MONITOR EN LINEA                      -\n";
                print "-------------------------------------------------\n";
                $conexion = $sock -> accept(); # Ahora aceptamos las conexiones
                print "Conexion desde: ",inet_ntoa((unpack_sockaddr_in(getpeername $conexion))[1])," \n";
                print $conexion "Intruso\n";   # El mensaje que le enviaremos usando print
                $conexion->send("Estas muerto\n"); # Otro mensaje que enviaremos usando send
                #close ($conexion);
            }
        );
    }
    else {
        close ($conexion);
        $hilo_seg->detach;
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El punto es que funciona cuando activo el botón.

Código: Seleccionar todo
-------------------------------------------------
-         MONITOR EN LINEA                      -
-------------------------------------------------


El problema es cuando desactivo el botón, me sale el siguiente error:

Código: Seleccionar todo
-------------------------------------------------
-         MONITOR EN LINEA                      -
-------------------------------------------------
Use of uninitialized value $conexion in ref-to-glob cast at network.pl line 347


No puedo cerrar el socket y creo que también no estoy matando el hilo.

Me podría guiar alguien sobre esta situación, cuál debería ser la forma correcta de cerrar el socket y eliminar el hilo. Por favor.

Gracias por leer.

NotaPublicado: 2008-09-21 08:29 @395
por Jenda
La variable $conexion está ajustada sólo dentro de ese nuevo hilo. Así que no lo puedes cerrar desde otro hilo.

Otro problema es que el nuevo hilo termina después de completar la función que has mandado a threads->create(). Así que el mejor lugar para cruzar la conexión está dentro de esta función.

Si necesitas que el nuevo hilo tenga la conexión abierta o al menos acepte nuevas conexiones hasta que desactivas el botón, tienes que cambiar la función para que no termine y marcar con algún semáforo o algo así cuando quieras que termine.

NotaPublicado: 2008-09-22 16:05 @711
por eddycito
En primer lugar gracias por responder.

Lo que quiero es eliminar el hilo cuando desactivo el botón.

Parece que la función threads->detach; no funciona o no sirve para eliminar el hilo activo.

¿A que función debo llamar para que elimine el hilo activo?

NotaPublicado: 2008-09-22 18:24 @808
por Jenda
El hilo se elimina automáticamente después de ejecutar

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  $conexion->send("Estas muerto\n");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Así que es muy probablemente que el hilo se elimina antes de que desactivas el botón. El detach() solo elimina el resultado del hilo.

Si de verdad quieres matar el hilo antes de que puede completar su trabajo, puedes llamar a

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  $hilo_seg->kill('KILL')->detach();
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


pero eso es algo bastante violento. Es mejor usar un semáforo para señalizar al hilo que debe terminar. Dándole tiempo para arreglar las cosas que están incompletas, cerrar los handles, etc. etc.

NotaPublicado: 2008-09-22 21:54 @954
por eddycito
ok, gracias por ayudarme, probaré lo que me indicas, luego te comento cómo me fue.

Con respecto a tu español, no está mal. Ni cuenta me di. En mi opinión lo haces bien.

NotaPublicado: 2008-09-23 15:10 @673
por eddycito
Te comento que la función:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  $hilo_seg->kill('KILL')->detach();
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


No funciona, sigue el error.

Activo la primera vez y desactivo la primera vez, hasta ahí todo ok.

Pero quiero volver a activarlo me dice:

Código: Seleccionar todo
-------------------------------------------------
-         MONITOR EN LINEA                      -
-------------------------------------------------
threads 2 finished abnormally; no se ha podido crear el socket, porque ya esta siendo usado.


El punto es que no está matando al hilo.

¿No sabes de otra función que mate hilos?

De antemano, gracias.

NotaPublicado: 2008-09-23 16:43 @738
por Jenda
El punto es que sí que está matándolo, pero no le deja tiempo para cerrar los sockets. Posiblemente depende de tu sistema operativo porque el siguiente código funciona en Windows Vista:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use threads;
use IO::Socket::INET;

sub hilo_sub {
        my $sock = new IO::Socket::INET (
                        LocalHost => 'localhost',
                        LocalPort => 1100,
                        Proto     => 'tcp',
                        Listen    =>  6,
                        Reuse     => 1
        );
        die "No se ha podido crear el socket: $!\n" unless $sock;
        print "-------------------------------------------------\n";
        print "-         MONITOR EN LINEA                      -\n";
        print "-------------------------------------------------\n";
        my $conexion = $sock -> accept(); # Ahora aceptamos las conexiones
        print "Conexion desde: ",inet_ntoa((unpack_sockaddr_in(getpeername $conexion))[1])," \n";
        print $conexion "Intruso\n";   # El mensaje que le enviaremos usando print
        $conexion->send("Estas muerto\n"); # Otro mensaje que enviaremos usando send
        #close ($conexion);
}


my $hilo_seg = threads->create( \&hilo_sub );
print "Waiting in the parent thread\n";
<STDIN>;
$hilo_seg->kill('KILL')->detach();
print "Killed\n";
<STDIN>;
$hilo_seg = threads->create( \&hilo_sub );
print "Waiting in the parent thread\n";
<STDIN>;
$hilo_seg->kill('KILL')->detach();
print "Killed\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¿Que hace en tu computadora?

Una posibilidad podría ser mandar algún otra señal. ¡Prueba algo así! Yo no puedo porque el único Unix que tengo acceso tiene un Perl muy viejo.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use threads;
use IO::Socket::INET;

sub hilo_sub {
        my $sock = new IO::Socket::INET (
                        LocalHost => 'localhost',
                        LocalPort => 1100,
                        Proto     => 'tcp',
                        Listen    =>  6,
                        Reuse     => 1
        );

        $SIG{'INT'} = sub {print "Ha recibido un signal\n"};
        die "No se ha podido crear el socket: $!\n" unless $sock;
        print "-------------------------------------------------\n";
        print "-         MONITOR EN LINEA                      -\n";
        print "-------------------------------------------------\n";
        my $conexion = $sock -> accept(); # Ahora aceptamos las conexiones
        if ($conexion) {
                print "Conexion desde: ",inet_ntoa((unpack_sockaddr_in(getpeername $conexion))[1])," \n";
                print $conexion "Intruso\n";   # El mensaje que le enviaremos usando print
                $conexion->send("Estas muerto\n"); # Otro mensaje que enviaremos usando send
                #close ($conexion);
        } else {
                print "Ninguna conexion!\n";
        }
}


my $hilo_seg = threads->create( \&hilo_sub );
print "Waiting in the parent thread\n";
<STDIN>;
$hilo_seg->kill('INT')->detach();
print "Killed\n";
<STDIN>;
$hilo_seg = threads->create( \&hilo_sub );
print "Waiting in the parent thread\n";
<STDIN>;
$hilo_seg->kill('INT')->detach();
print "Killed\n";
<STDIN>;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

NotaPublicado: 2008-09-23 17:24 @766
por eddycito
Ok, Gracias. Probando.

NotaPublicado: 2008-09-25 22:09 @965
por eddycito
Lamento comunicarte, que sigue sin funcionar. No entiende porqué.

Bueno, yo estoy programando en gtk2-Perl. Y estoy utilizando un toggle botón que activa la función ActivarS:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $activar_seg = Gtk2::ToggleToolButton->new_from_stock('gtk-dialog-authentication');
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$activar_seg->signal_connect (clicked => \&ActivaS);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En cuya función se hacen los controles de activación y desactivación del botón.
Por la activación del botón crea el hilo y el socket.
por la desactivación del botón debería eliminar el hilo y el socket.

Lo cual no funciona.

Ya probé lo que me indicaste, pero nada.

Me sigue saliendo el error.
Código: Seleccionar todo
threads 2 finished abnormally; no se ha podido crear el socket, porque ya esta siendo usado.


cuando activo el botón por segunda vez.

¿Qué podrá ser? No lo entiendo. Lógicamente parece que está bien, pero a la hora de ejecución no se da el caso.

NotaPublicado: 2008-09-26 05:53 @287
por Jenda
Y el código que te mandé hace lo mismo, ¿verdad?

Pues... parece que necesitas preguntar en otro foro. Prueba en http://www.perlmonks.org. Allí viene más gente con más experiencia con threads.

No olvides especificar tu versión de Perl y tu sistema operativo.