Is there a way to open a TCP Socket with a try/catch structure in case of timeouts?

Hi everyone,

I’m a programmer who is also a beginner in Ruby. I’ve inherited a Ruby program from another colleague, and I need to figure out the syntax to safely modify the original code.

The original code accepts a data record (a linked list, perhaps, I’m not sure) from an external source. The code then opens a socket on TCP 12345, sends the entire record, and then listens to the socket for a response from the remote host. The remote guy does some analysis and then sends back a string. The Ruby code then takes that string and appends it to the data record in a new field called “new_information”. Here’s the code:

require 'socket'
...accept data record "event"...
socket = TCPSocket.new("192.168.3.1", 12345)
socket.write (event.to_hash).to_s
response = socket.recv(1000)
socket.close
event.set("new_information", response)

All of this works flawlessly. (For those who are curious, this is part of a Logstash implementation. Logstash allows Ruby code to help process incoming log records.)

But now I’m worried about the scenario where the remote host is down and unavailable. I need to include an if/else or try/catch structure so that if the Ruby socket times out and no answer is ever received, the “new_information” field can still be populated with something meaningful. Here’s my stab at the modified code:

require 'socket'
...accept data record "event"...
begin
   socket = TCPSocket.new("192.168.3.1", 12345)
   socket.write (event.to_hash).to_s
   response = socket.recv(1000)
   socket.close
   event.set("new_information", response)
rescue Errno::ETIMEDOUT
   p 'timeout'
   event.set("new_information", "remote_svr_down!")
end

As you can probably tell, I don’t really know what I’m doing. Trouble is, the Logstash system with which I am working does not allow you to see the precise syntax error when the code crashes. So I have no idea if my modified code is nearly correct or way, way off.

Another question I have is… how long is the socket timeout here? I assume it is the default value. Is there a way to set that?

FULL DISCLOSURE :: I have also posted this question here.

Are you talking about this?

Code (getting error even with header):

#!/usr/bin/ruby -w
require 'socket'

server = TCPServer.new 2000

while true
	client = server.accept
	client.puts %Q<HTTP/1.1 200\r\nContent-Type: text/html;charset="utf-8"\r\nContent-Length: 1200\r\ncontent-encoding:gzip\r\n\r\n>
	client.puts IO.read('p.html.gz')
	client.close
end

If yes, I suggest strongly use WEBRick or perhaps Unicorn:

https://www.rubydoc.info/gems/unicorn/2.0.0/Unicorn/HttpServer

Or maybe Puma: