ruby sockets tcp gets

Recuperarse de un socket TCP roto en Ruby cuando está en get()



sockets gets (5)

Si crees que el rdoc para los zócalos de rubí, no implementa get . Esto me lleva a pensar que get está siendo proporcionado por un nivel más alto de abstracción (¿tal vez las bibliotecas IO?) Y probablemente no esté al tanto de cosas específicas del socket como ''connection closed''.

Intenta usar recvfrom lugar de gets

Estoy leyendo líneas de entrada en un socket TCP, similar a esto:

class Bla def getcmd @sock.gets unless @sock.closed? end def start srv = TCPServer.new(5000) @sock = srv.accept while ! @sock.closed? ans = getcmd end end end

Si el punto extremo finaliza la conexión mientras getline () se está ejecutando, gets () se cuelga.

¿Cómo puedo solucionar esto? ¿Es necesario hacer E / S sin bloqueo o temporizadas?


¿El IO # cerrado? devuelve verdadero cuando tanto el lector como el escritor están cerrados. En su caso, @eck.gets devuelve nil, y luego llama al getcmd nuevamente, y esto se ejecuta en un ciclo interminable. Puede usar select o cerrar el socket cuando obtiene return nil.


Puede usar seleccionar para ver si puede obtener de manera segura desde el socket; consulte la siguiente implementación de un TCPServer utilizando esta técnica.

require ''socket'' host, port = ''localhost'', 7000 TCPServer.open(host, port) do |server| while client = server.accept readfds = true got = nil begin readfds, writefds, exceptfds = select([client], nil, nil, 0.1) p :r => readfds, :w => writefds, :e => exceptfds if readfds got = client.gets p got end end while got end end

Y aquí un cliente que intenta romper el servidor:

require ''socket'' host, port = ''localhost'', 7000 TCPSocket.open(host, port) do |socket| socket.puts "Hey there" socket.write ''he'' socket.flush socket.close end


Recomiendo usar readpartial para leer desde su socket y también detectar reinicios entre iguales:

while true sockets_ready = select(@sockets, nil, nil, nil) if sockets_ready != nil sockets_ready[0].each do |socket| begin if (socket == @server_socket) # puts "Connection accepted!" @sockets << @server_socket.accept else # Received something on a client socket if socket.eof? # puts "Disconnect!" socket.close @sockets.delete(socket) else data = "" recv_length = 256 while (tmp = socket.readpartial(recv_length)) data += tmp break if (!socket.ready?) end listen socket, data end end rescue Exception => exception case exception when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT # puts "Socket: #{exception.class}" @sockets.delete(socket) else raise exception end end end end end

Este código toma prestado en gran medida de un buen código de IBM por M. Tim Jones. Tenga en cuenta que @server_socket está inicializado por:

@server_socket = TCPServer.open(port)

@sockets es solo una variedad de sockets.


Simplemente pgrep "ruby" para encontrar el pid, y matar -9 el pid y reiniciar.