2011-05-29 10 views
11

Tengo un código que estoy usando para obtener datos de un socket de red. Funciona bien, pero me abrí camino a través de ensayo y error. Humildemente confieso que no entiendo completamente cómo funciona, pero realmente me gustaría. (Esta era la carga de trabajo de código culted forma que encontré)Comprensión de IO.select when reading socket en Ruby

La parte que no entiendo comienza con "listo = IO.select ..." Estoy claro en:

  1. Lo IO.select anda (he intentado mirar hacia arriba, pero tengo aún más confusa con el núcleo y qué-no)
  2. lo que el argumento de matriz a IO.select es para
  3. lo dispuesto [0] está haciendo
  4. la idea general de leyendo 1024 bytes? a la vez

Aquí está el código:

@mysocket = TCPSocket.new('192.168.1.1', 9761) 

th = Thread.new do 
    while true 
     ready = IO.select([@mysocket]) 
     readable = ready[0] 

     readable.each do |socket| 
      if socket == @mysocket 
       buf = @mysocket.recv_nonblock(1024) 
       if buf.length == 0 
        puts "The server connection is dead. Exiting." 
        exit 
       else 
        puts "Received a message" 
       end 
      end 
     end 

    end 
end 

Gracias de antemano por ayudarme "aprender a pescar". Odio tener partes de mi código que no entiendo completamente, solo funciona por coincidencia.

+0

Pero, ¿por qué usas un hilo nuevo? ¿Cuáles son los pros y los contras de eso? – DiegoSalazar

+0

Corrí el ejemplo poniendo un montón de 'puts' dentro y no puedo entender por qué el programa nunca entra en el bucle' while true' (o puede ser 'puts' salida dentro del bucle nunca llega a la consola?) – Paul

Respuesta

17

1) IO.select toma un conjunto de sockets y espera hasta que sea posible leer o escribir con ellos (o si ocurre un error). Devuelve el evento de sockets que sucedió con.

2) la matriz contiene conectores que se verifican para detectar eventos. En su caso, solo especifica tomas para leer.

3) IO.select devuelve una matriz de matrices de sockets. El elemento 0 contiene conectores de los que puede leer, elemento 1 - conectores en los que puede escribir y elemento 2 - conectores con errores.

Después de obtener la lista de enchufes, puede leer los datos.

4) sí, recv_nonblock argumento es el tamaño en byte. Tenga en cuenta que el tamaño de los datos que se leen realmente puede ser inferior a 1024, en este caso puede necesitar repetir select (si los datos reales son importantes para usted).

+0

Así que, básicamente, esto es no usar seleccionar con un argumento de tiempo de espera para determinar si un socket está activo, pero está usando #recv para verificar si es posible obtener unos 1024 bytes de datos, y si no lo está, determina que el socket está muerto, ¿verdad? ? Pero entonces ... ¿qué pasa si simplemente no hay datos para leer en este momento (que podría venir más tarde)? ¿Cómo puede este tipo de verificación ser una buena forma de saber si una conexión está muerta? ¿Cuál es la parte (grande) de la que no estoy obteniendo? Gracias.. –

Cuestiones relacionadas