2011-09-13 6 views
1

저는 고객 태양계의 전력 출력을 모니터링하기위한 웹 애플리케이션을 개발하는 기계 엔지니어 (프로그래밍에 초보자)에 불과합니다. 현재 응용 프로그램이 소켓 연결을 열고 시간 초과 및 스레드를 사용하여 고객 인버터를 쿼리하는 데 사용하는 스크립트를 구현하려고합니다. 현재 (15 분마다 실행 크론 통해 설정됩니다) 스크립트는 매우 간단하다이 같은 같습니다 일몰 후 매일 : 나는 아무것도하기 전에 해결하려는 큰 문제의루비 소켓에 타임 아웃을 구현하는 가장 좋은 방법

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.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)은 시스템이 이미 "너무 오래"되었지만 2 초가 넘지 않았 으면이 코드가 연결을 다시 시도하기 때문에 6 번 줄에 나타 납니까? 또한 내가 읽은에서 Errno :: EINPROGRESS Windows 것 같습니다. Mac OS는 무엇이 될까요? 또는이 질문은 완전히 요점과 다를 수 있습니다. 내가 올바른 방향으로 가고 있다면 어느쪽으로 든 알려주 길 바란다. 또는이 작업을 수행 할 수있는 올바른 방법을 보여주는 주석 처리 된 스 니펫을 제공 할 수 있다면.

두 번째로, 소켓이 잘 연결되면 어떻게 소켓 (socket.read)의 타임 아웃을 구현하여 모든 것을 멈추게 할 수 있습니까? (실제로는 인버터가 종료 될 때 실제로 일어나는 것입니다)? 나는 루비 timeout.rb가 사용되어서는 안된다는 것을 계속 읽고있다. 몇 초 동안 읽기만 시도한 다음 소켓이 닫히면 소켓을 닫을 수 있습니까? 미리 감사드립니다.

답변

1

지금부터 이해할 수 있듯이, 내 소켓 연결 시도 시간을 단축하고 socket.read time out을 시도하려는이 문제를 피하기 위해 가장 쉬운 방법입니다 (반드시 최선은 아님 - 필요에 따라 다름). 내 스크립트가 간단하고 Ruby 1.8.7을 사용하고 있기 때문에 system_timer gem을 사용하고 있습니다 (Ruby의 타임 아웃 라이브러리는 Ruby 1.8.x에서는 신뢰할 수없고 system_timer는 Ruby 1.8.x에서 시간 초과 문제를 해결합니다).

http://systemtimer.rubyforge.org/

문서는 좋다.

관련 문제