Ruby socket programming


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

Ruby uniformly supports application network protocols, such as FTP, HTTP, etc.

Whether it is high-level or low-level. Ruby provides some basic classes that allow you to interact using TCP, UDP, SOCKS and many other protocols without having to stick to the network layer. These classes also provide helper classes that allow you to easily read and write to the server.

Next let us learn how to program Ruby Socket


What are Sockets

When the application layer communicates data through the transport layer, TCP and UDP will Encountering issues with concurrently servicing 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 the interaction between applications and the TCP/IP protocol to distinguish network communications and connections between different application processes.

Generate a socket with three main parameters: the destination IP address of the 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" Socket, the application layer can communicate with the transport layer through the socket interface to distinguish communications from different application processes or network connections, and implement concurrent services for data transmission.

Sockets Vocabulary analysis:

OptionDescription
domainIndicate the protocol family used, usually PF_INET, PF_UNIX, PF_X25, etc.
typeSpecify the socket type: SOCK_STREAM or SOCK_DGRAM. The Socket interface also defines the original Socket (SOCK_RAW), allowing the program to use low-level protocols
protocolUsually assigned a value of 0.
hostnameIdentifier of the network interface:
  • String, can be a host name or IP address

  • String "<broadcast>", specifies the INADDR_BROADCAST address.

  • 0 length string, specifying INADDR_ANY

  • An integer interpreted as a binary address in host byte order.

portport is the port number. Each server will listen to one or more port numbers for client connections. A port number can be a Fixnum port number, which contains the server name and port.

Simple client

Below we write a simple client instance with a given host and port. The Ruby TCPSocket class provides the open method to open a socket.

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

Once you open a Socket connection, you can read it like an IO object, and when you are done, you need to close the connection like a file.

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

require 'socket'      # Sockets 是标准库

hostname = 'localhost'
port = 2000

s = TCPSocket.open(hostname, port)

while line = s.gets   # 从 socket 中读取每行数据
  puts line.chop      # 打印到终端
end
s.close               # 关闭 socket

Simple service

Ruby You can use the TCPServer class to write a simple service. The TCPServer object is the factory object of TCPSocket.

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

Next call the accept method of TCPServer. This method will wait until a client connects to the specified port, and then returns a TCPSocket object to indicate the connection to the client.

require 'socket'               # 获取socket标准库

server = TCPServer.open(2000)  # Socket 监听端口为 2000
loop {                         # 永久运行服务
  client = server.accept       # 等待客户端连接
  client.puts(Time.now.ctime)  # 发送时间到客户端
  client.puts "Closing the connection. Bye!"
  client.close                 # 关闭客户端连接
}

Now, run the above code on the server to see the effect.


Multi-client TCP service

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

Ruby's Thread class makes it easy to create multi-threaded services, where one thread performs client connections while the main thread waits for more connections.

require 'socket'                # 获取socket标准库

server = TCPServer.open(2000)   # Socket 监听端口为 2000
loop {                          # 永久运行服务
  Thread.start(server.accept) do |client|
    client.puts(Time.now.ctime) # 发送时间到客户端
	client.puts "Closing the connection. Bye!"
    client.close                # 关闭客户端连接
  end
}

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


Tiny Web Browser

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

require 'socket'
 
host = 'www.w3cschool.cc'     # web服务器
port = 80                           # 默认 HTTP 端口
path = "/index.htm"                 # 想要获取的文件地址

# 这是个 HTTP 请求
request = "GET #{path} HTTP/1.0\r\n\r\n"

socket = TCPSocket.open(host,port)  # 连接服务器
socket.print(request)               # 发送请求
response = socket.read              # 读取完整的响应
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2) 
print body                          # 输出结果

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:


require 'net/http'                  # 我们需要的库
host = 'www.w3cschool.cc'           #  web 服务器
path = '/index.htm'                 # 我们想要的文件 

http = Net::HTTP.new(host)          # 创建连接
headers, body = http.get(path)      # 请求文件
if headers.code == "200"            # 检测状态码
  print body                        
else                                
  puts "#{headers.code} #{headers.message}" 
end

Above we just briefly introduce the application of socket in Ruby, more For more documentation, please see: Ruby Socket library and class methods