2008-10-23 33 views
19

Làm cách nào để đặt thời gian chờ để chặn các thao tác trên ổ cắm Ruby?Làm cách nào để đặt thời gian chờ của ổ cắm trong Ruby?

+2

Tìm thấy giải pháp tốt hơn nhiều so với giải pháp được chấp nhận của bạn tại đây: http://stackoverflow.com/a/12111120/216314 –

+0

http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/Timeout.html –

+0

[Mô-đun thời gian chờ có khóa độc quyền] (http://stackoverflow.com/a/15304835/1301972). –

Trả lời

17

Giải pháp tôi thấy xuất hiện để làm việc là sử dụng Timeout::timeout:

require 'timeout' 
    ... 
begin 
    timeout(5) do 
     message, client_address = some_socket.recvfrom(1024) 
    end 
rescue Timeout::Error 
    puts "Timed out!" 
end 
+13

Sử dụng thời gian chờ là một sai lầm. Do theards màu xanh lá cây, bất cứ điều gì mà khối trên IO sẽ ngăn chặn các chuỗi thời gian chờ cũng như vậy ngăn chặn nó làm việc. – Sardathrion

+0

@Sardathrion, cảm ơn vì phản hồi nhưng giải pháp sẽ tốt hơn bình luận tiêu cực :) – Mike

+1

Các chuỗi Ruby bị hỏng Tôi sợ. Tìm một ngôn ngữ tốt hơn - khắc nghiệt nhưng đúng sự thật. – Sardathrion

15

Đối tượng timeout là một giải pháp tốt.

Đây là một ví dụ về không đồng bộ I/O (non-blocking trong tự nhiên và xảy ra không đồng bộ để dòng chảy của ứng dụng.)

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

có thể được sử dụng để có được những tác dụng tương tự.

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

Tôi nghĩ rằng phương pháp chặn không phải là cách để thực hiện.
Tôi đã thử đề cập ở trên và vẫn có thể bị treo.
bài viết này non blocking networking và cách tiếp cận của jonke ở trên đã giúp tôi đi đúng hướng. Máy chủ của tôi đã chặn kết nối ban đầu vì vậy tôi cần nó ở mức thấp hơn một chút.
các rdoc ổ cắm có thể cho biết thêm chi tiết vào 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 

để có được một thử nghiệm tốt. khởi động một máy chủ socket đơn giản và sau đó thực hiện ctrl-z để background nó

IO.select đang chờ dữ liệu đến trên luồng đầu vào trong vòng 10 giây. điều này có thể không hoạt động nếu đó không phải là trường hợp.

Nó phải là một sự thay thế tốt cho phương pháp mở của TCPSocket.

+0

Điều này làm việc rất tốt cho tôi. Thời gian chờ không nên được sử dụng trong bất kỳ trường hợp nào vì các chủ đề màu xanh lá cây của MRI. – Sardathrion

+2

Kết nối không chặn có thể ghi được khi sẵn sàng. Sử dụng 'IO.select (nil, [sock], nil, timeout.to_i)' – tmm1

+0

Chỉ làm việc cho tôi sau khi sử dụng nhận xét của tmm1. –

Các vấn đề liên quan