Socket from python to ruby


#1

I’d want to port this code from python to ruby:

self.sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
self.sckt.bind((self.CFG[‘smsc’][‘local_host’],
self.CFG[‘smsc’][‘local_port’]))
self.sckt.connect((self.CFG[‘smsc’][‘remote_host’],
self.CFG[‘smsc’][‘remote_port’]))
self.sckt.send(mex)
recv = self.sckt.recv(4096)
self.sckt.close()

The remote host is a router for an SMSC service.
The script is tested and works correctly.
I don’t understand if I’ve to create a client or a server socket…

bye

Devis_


#2

Devis Battisti wrote:

I’d want to port this code from python to ruby:

self.sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
self.sckt.bind((self.CFG[‘smsc’][‘local_host’],
self.CFG[‘smsc’][‘local_port’]))
self.sckt.connect((self.CFG[‘smsc’][‘remote_host’],
self.CFG[‘smsc’][‘remote_port’]))
self.sckt.send(mex)
recv = self.sckt.recv(4096)
self.sckt.close()

The remote host is a router for an SMSC service.
The script is tested and works correctly.
I don’t understand if I’ve to create a client or a server socket…

Since you are using TCP and calling ‘connect’, it’s a client socket.

However, they have (unusually) decided to bind the socket to a specific
local port. This might be because of firewall rules.

Without this you could just do:

s = TCPSocket.new(cfg.remote_host, cfg.remote_port)
s.write(mex)
recv = s.read(4096)

If you really need to bind the local port for an outbound connection, I
think you’ll have to use the lower-level Socket class directly, which is
not particularly well documented, but should correspond roughly to your
python code. Unfortunately you’ll need to do some sockaddr packing.

http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_network.html


#3

It’s not so hard after all:

require ‘socket’
local_host = “127.0.0.1”
local_port = 1234
remote_host = “127.0.0.1”
remote_port = 80
s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
s.bind(Socket.pack_sockaddr_in(local_port, local_host))
s.connect(Socket.pack_sockaddr_in(remote_port, remote_host))
s.write “GET / HTTP/1.0\r\n\r\n”
puts s.recv(4096)

I found useful examples at
http://www.ruby-doc.org/stdlib/libdoc/socket/rdoc/classes/Socket.html#M004233
http://www.ruby-doc.org/stdlib/libdoc/socket/rdoc/classes/Socket.html#M004231

The documentation is much better than when I last looked - although
Socket.new doesn’t seem to be shown.

HTH,

Brian.


#4

Brian C. wrote:

However, they have (unusually) decided to bind the socket to a specific
local port. This might be because of firewall rules.

Without this you could just do:

s = TCPSocket.new(cfg.remote_host, cfg.remote_port)

TCPSocket::open accepts local host and port args, from the docs (1.8.7):

TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)

Regards
Stefan


#5

Stefan R. wrote:

TCPSocket::open accepts local host and port args, from the docs (1.8.7):

Thank you. If this were just 1.8.7 then I wouldn’t be interested, but
actually it works for 1.8.6 too.

My “Programming Ruby” (2nd edition, p771) lists only the two parameters
for TCPSocket.new. That book was written against 1.8.2, so looks like it
was added some time after then.


#6

Thanks to everybody, it works!


#7

However, they have (unusually) decided to bind the socket to a specific
local port. This might be because of firewall rules.

yes, I thin so.

Without this you could just do:

s = TCPSocket.new(cfg.remote_host, cfg.remote_port)
s.write(mex)
recv = s.read(4096)

no, it doesn’t work: it remains in attemp of response.

If you really need to bind the local port for an outbound connection, I
think you’ll have to use the lower-level Socket class directly, which is
not particularly well documented, but should correspond roughly to your
python code. Unfortunately you’ll need to do some sockaddr packing.

http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_network.html

thanks for the answer, I will continue to try…

Devis_