Reputation: 137
I'm connecting to a TCP server using Ruby's TCPSocket class.
I send some data about an address and I must wait for the server to do some processing to give me the geocoding of said address. Since the process in the server takes some time, I cannot read the response immediately.
When I used socket.readpartial()
I got a response of two white spaces.
I temporarily solved this using sleep(5)
but I don't like this at all, because it is hackish and clumsy, and I risk that even after 5 seconds the response is not ready and I still get an empty response.
I know that the responses will always be 285 characters long.
Is there a more correct and elegant way of having my TCP socket wait for the full response?
Here's my code:
def matchgeocode(rua, nro, cidade, uf)
count = 0
begin
socket = TCPSocket.new(GEOCODER_URL, GEOCODER_PORT)
# Needed for authentication
socket.write("TICKET #{GEOCODER_TICKET}")
socket.read(2)
# Here's the message I send to the server
socket.write("MATCHGEOCODE -Rua:\"#{rua}\" -Nro:#{nro} -Cidade:\"#{cidade}\" -Uf:\"#{uf}\"")
# My hackish sleep
sleep(5)
# Reading the fixed size response
response = socket.readpartial(285)
socket.write('QUIT')
socket.close
rescue Exception => e
count += 1
puts e.message
if count <= 5 && response.eql?('')
retry
end
end
response
end
Upvotes: 1
Views: 1684
Reputation: 34328
Since you know the length of the response you should use read
, not readpartial
.
readpartial
returns immediately if ANY data is available, even one byte is enough. That's why you need the sleep
call so that the response has time to return to you before readpartial
tries to peek at what data is present.
read
on the other hand blocks completely until ALL requested data is available. Since you know the length of the result then read
is the natural solution here.
Upvotes: 1