Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Ruby Socket programming


May 12, 2021 Ruby


Table of contents


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 basic socket support for clients and servers for connection-oriented and connectionless protocols.

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

Whether it's at the top or the bottom. R uby provides some basic classes that allow you to interact with many protocols, such as TCP, UDP, SOCKS, and so on, without having to stick to the network layer. T hese classes also provide secondary classes that make it easy to read and write to the server.

Let's then learn how to program Ruby Socket


What is Sockets

When the application layer communicates data through the transport layer, TCP and UDP experience the problem of providing simultaneous services for multiple application processes at the same time. M ultiple TCP connections or multiple application processes may need to transfer data over the same TCP protocol port. T o distinguish between different application processes and connections, many computer operating systems provide an interface called socket for applications to interact with the TCP/IP protocol, distinguishing between network traffic and connections between different application processes.

There are three main parameters for generating sockets: the destination IP address of the communication, the transport layer protocol (TCP or UDP) used, and the port number used. S ocket was meant to be a socket. B y combining these three parameters with a "socket" Socket binding, the application layer and the transport layer can distinguish between communications from different application processes or network connections through a socket interface to achieve a data transfer of the same service.

Sockets Vocabulary Analysis:

Options Describe
domain Indicates the protocol family used, usually PF_INET, PF_UNIX, PF_X25, and so on.
type Specify the type of socket: SOCK_STREAM or SOCK_DGRAM, the Socket interface also defines the original socket (SOCK_RAW), allowing programs to use low-level protocols
protocol Usually assigned a value of 0.
hostname Identification of the network interface:
  • String, which can be a host name or AN address
  • The string, ""INADDR_BROADCAST"
  • A string of 0 lengths, specifying INADDR_ANY
  • An integer, interpreted as a binary address in the host byte order.
port Port is the port number, and each server listens for one or more port numbers that the client connects to, and a port number that can be Fixnum's port number, including the server name and port.

Simple client

Below we have written a simple client instance with a given host and port, and the Ruby TCPSocket class provides an open method to open a socke.

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

Once you open an Socket connection, you can read it like an IO object, and when you're done, you need to close the connection as if you were closing a file.

The following example shows how to connect to a specified host, read data from the socket, and finally turn off 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 can use the TCPServer class to write a simple service. The TCPServer object is the factory object of TCPSocket.

Now let's use TCPServer.open (hostname, port) to create a TCPServer object.

Next, call the TCPServer's accept method, which waits until a client connects to the specified port, and then returns a TCPSocket object, indicating a 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 a multithreaded service where a thread performs a client connection 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, socket runs permanently, and when server.accept receives a connection from the client, a new thread is created and the request is processed immediately. The main program loops back immediately 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.cn'     # 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 a pre-built library for HTTP such as Net::HTTP.

The following code is equivalent to the previous code:

require 'net/http'                  # 我们需要的库
host = 'www.w3cschool.cn'           #  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're just going to introduce you to the socket app in Ruby, see more documentation: Ruby Socket Library and Class Methods