mercredi 3 juin 2015

How does Ruby manage localhost communications via TCP under Windows 7?

I am trying to implement a simple local TCP communication between a Ruby server and a C++ library interfaced to Unreal Engine 4.

I have used some sample code for the ruby server, which uses the socket library and instanciates a TCPServer:

require 'socket'

puts "Starting up server..."
# establish the server
## Server established to listen for connections on port 2008
server = TCPServer.new(15300)
# setup to listen and accept connections
while (session = server.accept)
 #start new thread conversation
 ## Here we will establish a new thread for a connection client
 Thread.start do
   ## I want to be sure to output something on the server side
   ## to show that there has been a connection
   puts "log: Connection from #{session.peeraddr[2]} at
          #{session.peeraddr[3]}"
   puts "log: got input from client"
   ## lets see what the client has to say by grabbing the input
   ## then display it. Please note that the session.gets will look
   ## for an end of line character "\n" before moving forward.
   input = session.gets
   puts input
   ## Lets respond with a nice warm welcome message
   session.puts "Server: Welcome #{session.peeraddr[2]}\n"
   # reply with goodbye
   ## now lets end the session since all we wanted to do is
   ## acknowledge the client
   puts "log: sending goodbye"
   session.puts "Server: Goodbye\n"
 end  #end thread conversation
end   #end loop

This application, if tested with a ruby client, works perfectly fine.

This is the client:

require 'socket'
# establish connection
## We need to tell the client where to connect
## Conveniently it is on localhost at port 15300!
clientSession = TCPSocket.new( "localhost", 15300 )
puts "log: starting connection"
#send a quick message
## Note that this has a carriage return. Remember our server
## uses the method gets() to get input back from the server.
puts "log: saying hello"
clientSession.puts "Client: Hello Server World!\n"
#wait for messages from the server
## You've sent your message, now we need to make sure
## the session isn't closed, spit out any messages the server
## has to say, and check to see if any of those messages
## contain 'Goodbye'. If they do we can close the connection
 while !(clientSession.closed?) &&
          (serverMessage = clientSession.gets)
  ## lets output our server messages
  puts serverMessage
  #if one of the messages contains 'Goodbye' we'll disconnect
  ## we disconnect by 'closing' the session.
  if serverMessage.include?("Goodbye")
   puts "log: closing connection"
   clientSession.close
  end
 end #end loop

Server output:

Starting up server...
log: Connection from ::1 at
          ::1
log: got input from client
Client: Hello Server World!
log: sending goodbye

But when I try to connect to the server using C++11 and the TCP functions in Unreal Engine 4 I do not get any kind of response from the server implemented in ruby (not even "Connection from...").

To understand what was the problem I tried to run some netwrok analysis, starting from the simplest (Window's Resource Monitor), to the most complex (ZenMap). In no case there was a single service running with the selected port open (port 15300). I have double checked every single possible cause for this (e.g. firewall, other security software) but there was no block to the ruby interpreter.

In order to understand why such a simple application is not working I started using Wireshark. It was then that I noticed that there is no local loopback interface, which required me to use RawCap (wich manages to capture the local communications and dump them on file). Using it I managed to dump the local communications on my machine during both a run of the ruby client/server pair and Cygwin Socat/Unreal Engine 4. What I found was pretty baffling: there were NO open local TCP sockets on the port for the ruby pair (port 15300), but the TCP ports opened by Unreal Engine 4 were there (along with port 15301, the one I used for the tests).

What I would like to understand is:

  • As there is no local loopback interface how does ruby communicate through local TCP sockets?
  • How is it possible that if I open a TCPServer with ruby on a specific TCP port that port does not show anywhere but Ruby can still communicate through that port between two different processes?
  • On the light of the two previous questions, how do I communicate between Ruby and C++11 (regardless of Unreal Engine 4)

Aucun commentaire:

Enregistrer un commentaire