저는 고객 태양계의 전력 출력을 모니터링하기위한 웹 애플리케이션을 개발하는 기계 엔지니어 (프로그래밍에 초보자)에 불과합니다. 현재 응용 프로그램이 소켓 연결을 열고 시간 초과 및 스레드를 사용하여 고객 인버터를 쿼리하는 데 사용하는 스크립트를 구현하려고합니다. 현재 (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가 사용되어서는 안된다는 것을 계속 읽고있다. 몇 초 동안 읽기만 시도한 다음 소켓이 닫히면 소켓을 닫을 수 있습니까? 미리 감사드립니다.