Socket In Brief, For Ruby
Friday
Mar 19, 2010
6:09 pm
This post is mainly for my reference, but someone is else is going to be looking for this information. This post is about how to use the low lever socket layer of ruby. in particular it is about how to get to a point where one can read and write over the connection. It covers the three major types sockets: UNIX, UDP and TCP. Most of the information here can be extracted for this page.
Server vs Socket
Before we get to into the code, the first this to not is the different use of *Socket and *Server classes. A Socket is what you eventually need to end up with in order to read and write over the connection. But for connection based protocols there is an intermediate step. The *Server class must be used to wait for an incoming connection it will then produce one *Socket instance for each connection. This second level of indirection must be dealt with for incoming links.
UNIXSocket
Unix Sockets use the file system as their address space. Connection points are a special type of file. The UNIXServer.new method will create the file if it does not already exist, but if it does it will fail. It is therefore suggested that (after taking precautions not to delete data) one unlink the any existing socket before creating a new one.
To listen for a connection on a UNIX Socket:
#!/ruby
file = 'path/to/my/socket'
File.unlink if File.exists(file) && File.socket?(file)
server = UNIXServer.new(file)
# return a UNIXSocket once a connection is made
socket = server.accept
# socket is now ready to communicate.
To connect to an already listening UNIX Server:
#!/ruby
file = 'path/to/my/socket'
socket = UNIXSocket.new(file)
UDPSocket
There are no connections with UDP which is just fine for an amazing number of applications. There is still the need to listen to or speak to a common address space. At the lowest level this is is a IP address and a port, but ruby will "do the right thing" if it is handed a url by resolving it and using that IP address.
A consequence of not having a connection is that UDP is asymetric to both read and write takes two open Sockets.
To listen for UDP on a port:
#!/ruby
host = 'localhost' #or "0.0.0.0"
port = 12345 #String works as well
socket = UDPSocket.new
socket.bind(host,port)
#socket can now read an incoming UDP stream
To write to a UDP port like it is a normal socket:
#!/ruby
host = 'udp.example.com' # or IP address
port = 12345 #String works as well
socket = UDPSocket.new
socket.connect(host, port)
TCPSocket
While TCP communication is commonly associated with HTTP it is not necessary to use that protocol. On the other hand if you wish to speak HTTP, FTP or some other well known protocol it is strongly suggested that you use the NET standard libraries. Like UNIX Sockets TCP Sockets have connections so a TCPServer is needed to receive a connection. Like UDP the TCP methods will play nicely with both IP addresses and urls.
To listen for a new TCP connection:
#!/ruby
host = 'localhost' #or "0.0.0.0"
port = 12345 #String works as well
server = TCPServer.new(host,port)
socket = server.accept
To open a connection to a TCP Server:
#!/ruby
host = 'udp.example.com' # or IP address
port = 12345 #String works as well
TCPSocket.new(host,port)
Note that here there is no need to use #connect as it is implied.