2008-08-18 9 views
11

Escribo mi primera aplicación Perl: un bot de AOL Instant Messenger que habla con un microcontrolador Arduino, que a su vez controla un servo que presionará el botón de encendido en el servidor de mi administrador, que se congela aleatoriamente cada 28 horas más o menos.¿Cómo puedo probar STDIN sin bloquear en Perl?

He terminado todas las cosas difíciles, solo intento agregar un último bit de código para romper el ciclo principal y cerrar la sesión de AIM cuando el usuario escribe 'salir'.

El problema es que, si trato de leer desde STDIN en el bucle principal del programa, bloquea el proceso hasta que se ingresa la entrada, esencialmente haciendo que el bot quede inactivo. He intentado probar EOF antes de leer, pero no hay ningún dado ... EOF simplemente siempre devuelve falso.

He aquí a continuación algunos ejemplos de código que estoy trabajando con:

while(1) { 
    $oscar->do_one_loop(); 

# Poll to see if any arduino data is coming in over serial port 
    my $char = $port->lookfor(); 

# If we get data from arduino, then print it 
    if ($char) { 
     print "" . $char ; 
    } 

    # reading STDIN blocks until input is received... AAARG! 
    my $a = <STDIN>; 
    print $a; 
    if($a eq "exit" || $a eq "quit" || $a eq 'c' || $a eq 'q') {last;} 
} 

print "Signing off... "; 

$oscar->signoff(); 
print "Done\n"; 
print "Closing serial port... "; 
$port->close() || warn "close failed"; 
print "Done\n"; 

Respuesta

17

El Perl incorporado es select(), que es un paso a través de la llamada al sistema select(), pero para la gente sana recomiendo IO::Select . muestra

Código:

#!/usr/bin/perl 

use IO::Select; 

$s = IO::Select->new(); 
$s->add(\*STDIN); 

while (++$i) { 
    print "Hiya $i!\n"; 
    sleep(5); 
    if ($s->can_read(.5)) { 
    chomp($foo = <STDIN>); 
    print "Got '$foo' from STDIN\n"; 
    } 
} 
+4

Gran nota a cualquier otra persona, 'IO :: Select' sólo funciona en UNIX, no funciona en Windows! – slm

+0

En realidad 'IO :: Select' y' select() 'en general en Windows funciona para (algunos) sockets de dominio de internet, pero solo eso. Windows es una plataforma asombrosamente rota, así que no esperes que una API multiplataforma tan simple funcione en todos los casos. Tienes que hacer una cosa para los sockets, otra para los archivos/named pipes, otra para los pipes anónimos/handle "Console", etc ... El hecho de que llamaran a su 'encuesta()' 'WPAPoll', solo lo hizo funcionar para enchufes de Internet, y se niegan a corregir errores conocidos porque "poll() está en desuso" debería ser una advertencia para ** mantenerse lejos **. – alexchandel

Cuestiones relacionadas