2011-09-13 33 views
1

我只是一個機械工程師(編程的新手)開發一個Web應用程序來監視客戶太陽能系統的功率輸出。我目前正試圖實現我的應用程序用來打開套接字連接並使用超時和線程查詢客戶逆變器的腳本。目前,該腳本(這是通過一個cron設置爲每15分鐘運行)是很瑣碎,看起來是這樣的:在ruby套接字上實現超時的最佳方式

System.all.each do |system| 
    @sock = TCPSocket.open(system.ip,51101) 
    @query = "\x0A\x05\x03\x00\xB5\x00\x01\x94\x68\x0D" 
    @sock.write(@query)  
    @s = @sock.read(9) 
    # do stuff with @s 
    @sock.close 
end 

一個我想任何事情之前要解決的大問題:每天在日落之後所有客戶逆變器在當天關閉,並且此腳本嘗試其第一個socket.write/read,我相信它會「掛起」,因爲爲了它再次開始連接和查詢,我必須在早上重新啓動計算機。所以我想在socket本身和socket.read上正確實現超時,這樣就不會發生這種情況。從堆棧溢出的研究,我迄今所做的,我想,也許我應該做的事情像下面這樣做如上同樣的事情,但有一個插口,超時2秒後:

@port = 51101 
System.all.each do |system| 
    @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) 
    @sock_address = Socket.sockaddr_in(@port, system.ip) 

    begin 
    @sock.connect_nonblock(@sock_address) 
    @query = "\x0A\x05\x03\x00\xB5\x00\x01\x94\x68\x0D" 
    @sock.write(@query)  
    @s = @sock.read(9) 
    # do stuff with @s 
    @sock.close 
    rescue Errno::EINPROGRESS 
    if IO.select(nil, [@sock], nil, 2) 
     begin 
     @sock.connect_nonblock(@sock_address) 
     @query = "\x0A\x05\x03\x00\xB5\x00\x01\x94\x68\x0D" 
     @sock.write(@query)  
     @s = @sock.read(9) 
     # do stuff with @s 
     @sock.close 
     rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH 
     # do something 
     end 
    end 
    end 
end 

但有是一些我不明白這個代碼的東西。首先,何時Errno :: EINPROGRESS提出?第二個@sock.connect_nonblock(@sock_address)是否出現在第6行,因爲如果系統已經嘗試了「太長」但不超過2秒,此代碼會重試連接?也從我讀Errno :: EINPROGRESS似乎是Windows的東西。什麼是Mac OS等價物?或者這些問題可能完全是問題。如果我走向正確的方向,請讓我知道任何一種方式。或者,如果你可以給我提供一個評論片段,展示正確的方式來做到這一點。其次,如果套接字連接良好,我怎麼能實現socket.read的超時,以便它不會讓所有事情都掛起(這是我認爲實際發生在逆變器關閉時)?我一直在閱讀,不應該使用ruby timeout.rb。我怎麼能讓它只嘗試閱讀幾秒鐘,然後關閉套接字,如果它掛起?提前謝謝你。

回答

1

從我現在瞭解的情況來看,它最簡單(不一定是最好的 - 取決於您的需求),只是爲了避免嘗試讓套接字連接嘗試超時以及套接字讀取超時的問題。由於我的腳本很簡單,而且我使用的是Ruby 1.8.7,我正在使用system_timer gem(ruby的超時庫對於Ruby 1.8.x不可靠,而system_timer在Ruby 1.8.x中解決了超時的問題)。

http://systemtimer.rubyforge.org/

文檔是不錯的。