Ruby Socket Programming

Ruby provides two levels of access to network services. At the low level, you can access the operating system, which allows you to implement basic socket support for clients and servers for connection-oriented and connectionless protocols.

Ruby provides unified support for application network protocols such as FTP, HTTP, etc.

Whether high-level or low-level, Ruby provides some basic classes that let you interact with many protocols such as TCP, UDP, SOCKS, without being tied to the network layer. These classes also provide helper classes that allow you to easily read from and write to servers.

Next, let's learn how to do Ruby Socket programming.


What are Sockets

When the application layer communicates with the transport layer for data communication, TCP and UDP encounter the problem of providing concurrent services to multiple application processes at the same time. Multiple TCP connections or multiple application processes may need to transmit data through the same TCP protocol port. In order to distinguish different application processes and connections, many computer operating systems provide an interface called a socket for applications to interact with TCP/IP protocols, distinguishing network communication and connections between different application processes.

Creating a socket mainly involves three parameters: the destination IP address for communication, the transport layer protocol used (TCP or UDP), and the port number used. The original meaning of Socket is "socket". By combining these three parameters and binding them to a "socket", the application layer can use the socket interface with the transport layer to distinguish communication from different application processes or network connections, enabling concurrent data transmission services.

Socket Terms:

OptionDescription
domainIndicates the protocol family used, usually PF_INET, PF_UNIX, PF_X25, etc.
typeSpecifies the type of socket: SOCK_STREAM or SOCK_DGRAM. The Socket interface also defines raw sockets (SOCK_RAW), allowing programs to use lower-level protocols.
protocolUsually assigned 0.
hostnameIdentifier of the network interface:
  • String, can be a host name or IP address
  • String "<broadcast>", specifies the INADDR_BROADCAST address.
  • Zero-length string, specifies INADDR_ANY
  • An integer, interpreted as a binary address in host byte order.
portport is the number of the port. Each server listens on one or more port numbers for client connections. A port number can be a Fixnum port number, or a string containing the server name and port.

Simple Client

Below we have written a simple client example using a given host and port. The Ruby TCPSocket class provides the open method to open a socket.

TCPSocket.open(hosname, port) opens a TCP connection.

Once you open a Socket connection, you can read from it like an IO object. When finished, you need to close the connection like closing a file.

The following example demonstrates how to connect to a specified host, read data from the socket, and finally close the socket:

Example

require 'socket' #Sockets is the standard library hostname = 'localhost' port = 2000 s = TCPSocket.open(hostname, port) while line = s.gets #Read each line of data from the socket puts line.chop #Print to terminal end s.close #Close socket

Simple Server

In Ruby, you can use the TCPServer class to write a simple service. A TCPServer object is a factory object for TCPSocket.

Now we use TCPServer.open(hostname, port) to create a TCPServer object.

Next, call the accept method of TCPServer. This method waits until a client connects to the specified port, then returns a TCPSocket object representing the connection to that client.

Example

require 'socket' #Get the socket standard library server = TCPServer.open(2000) #Socket listens on port 2000 loop { #Run service forever client = server.accept #Wait for client connection client.puts(Time.now.ctime) #Send time to client client.puts "Closing the connection. Bye!" client.close #Close client connection }

Now run the above code on the server and see the effect.


Multi-client TCP Service

On the Internet, most services have a large number of client connections.

Ruby's Thread class can easily create multi-threaded services. One thread handles client connections, while the main thread waits for more connections.

Example

require 'socket' #Get the socket standard library server = TCPServer.open(2000) #Socket listens on port 2000 loop { #Run service forever Thread.start(server.accept) do |client| client.puts(Time.now.ctime) #Send time to client client.puts "Closing the connection. Bye!" client.close #Close client connection end }

In this example, the socket runs forever. When server.accept receives a client connection, a new thread is created and immediately begins processing the request. The main program then immediately loops back and waits for new connections.


Tiny Web Browser

We can use the socket library to implement any Internet protocol. The following code shows how to retrieve the content of a web page:

Example

require 'socket' host = 'www.w3cschool.cc' #Web server port = 80 #Default HTTP port path = "/index.htm" #Path of the file to retrieve #This is an HTTP request request = "GET #{path} HTTP/1.0\r\n\r\n" socket = TCPSocket.open(host,port) #Connect to server socket.print(request) #Send request response = socket.read #Read the complete response # Split response at first blank line into headers and body headers,body = response.split("\r\n\r\n", 2) print body #Output result

To implement a web-like client, you can use pre-built libraries for HTTP such as Net::HTTP.

The following code is equivalent to the previous code:

Example

require 'net/http' #The library we need host = 'www.w3cschool.cc' #Web server path = '/index.htm' #The file we want http = Net::HTTP.new(host) #Create connection headers, body = http.get(path) #Request file if headers.code == "200" #Check status code print body else puts "#{headers.code} #{headers.message}" end

Above we have only briefly introduced the application of sockets in Ruby. For more documentation, please see:Ruby Socket Library and Class Methods

Other extensions