Как установить время ожидания сокета в Ruby? - PullRequest
19 голосов
/ 24 октября 2008

Как установить время ожидания для операций блокировки на сокете Ruby?

Ответы [ 3 ]

17 голосов
/ 24 октября 2008

Решение, которое я нашел и которое работает, заключается в использовании Timeout :: timeout :

require 'timeout'
    ...
begin 
    timeout(5) do
        message, client_address = some_socket.recvfrom(1024)
    end
rescue Timeout::Error
    puts "Timed out!"
end
15 голосов
/ 24 октября 2008

Объект тайм-аута является хорошим решением.

Это пример асинхронного ввода-вывода (неблокирующий по своей природе Ход подачи заявки.)

IO.select(read_array
[, write_array
[, error_array
[, timeout]]] ) => array or nil

Может использоваться для получения того же эффекта.

require 'socket'

strmSock1 = TCPSocket::new( "www.dn.se", 80 )
strmSock2 = TCPSocket::new( "www.svd.se", 80 )
# Block until one or more events are received
#result = select( [strmSock1, strmSock2, STDIN], nil, nil )
timeout=5

timeout=100
result = select( [strmSock1, strmSock2], nil, nil,timeout )
puts result.inspect
if result

  for inp in result[0]
    if inp == strmSock1 then
      # data avail on strmSock1
      puts "data avail on strmSock1"
    elsif inp == strmSock2 then
      # data avail on strmSock2
      puts "data avail on strmSock2"
    elsif inp == STDIN
      # data avail on STDIN
      puts "data avail on STDIN"
    end
  end
end
8 голосов
/ 07 мая 2010

Я думаю, что неблокирующий подход - это путь.
Я попробовал упомянутую выше статью и все еще мог заставить ее зависать.
эта статья неблокирующая сеть и описанный выше подход jonke привели меня на правильный путь Мой сервер блокировал исходное соединение, поэтому мне нужно было, чтобы он был немного ниже.
гнездо rdoc может дать более подробную информацию в connect_nonblock

def self.open(host, port, timeout=10)
 addr = Socket.getaddrinfo(host, nil)
 sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)

 begin
  sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
 rescue Errno::EINPROGRESS
  resp = IO.select([sock],nil, nil, timeout.to_i)
  if resp.nil?
    raise Errno::ECONNREFUSED
  end
  begin
    sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
  rescue Errno::EISCONN
  end
 end
 sock
end

чтобы получить хороший тест. запустите простой сервер сокетов, а затем выполните ctrl-z, чтобы создать фон

IO.select ожидает поступления данных во входной поток в течение 10 секунд. это может не сработать, если это не так.

Это должно быть хорошей заменой открытого метода TCPSocket.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...