Programmation de sockets Ruby


Ruby fournit deux niveaux d'accès au réseau. Au niveau inférieur, vous avez accès au système d'exploitation, ce qui vous permet d'implémenter des clients et des serveurs avec une prise en charge de base des sockets pour les protocoles orientés connexion et sans connexion.

Ruby prend en charge uniformément les protocoles réseau d'applications, tels que FTP, HTTP, etc.

Que ce soit en haut ou en bas. Ruby fournit des classes de base qui vous permettent d'interagir en utilisant TCP, UDP, SOCKS et de nombreux autres protocoles sans avoir à vous en tenir à la couche réseau. Ces classes fournissent également des classes d'assistance qui vous permettent de lire et d'écrire facilement sur le serveur.

Apprenons ensuite à programmer Ruby Socket


Que sont les Sockets

Lorsque la couche application communique des données via la couche de transport, TCP et UDP rencontreront des problèmes avec la gestion simultanée de plusieurs processus de candidature en même temps. Plusieurs connexions TCP ou plusieurs processus d'application peuvent devoir transmettre des données via le même port de protocole TCP. Afin de distinguer les différents processus et connexions d'application, de nombreux systèmes d'exploitation informatiques fournissent une interface appelée socket pour l'interaction entre les applications et le protocole TCP/IP afin de distinguer les communications réseau et les connexions entre les différents processus d'application.

Génère un socket avec trois paramètres principaux : l'adresse IP de destination de la communication, le protocole de couche transport utilisé (TCP ou UDP) et le numéro de port utilisé. La signification originale de Socket est « socket ». En combinant ces trois paramètres et en les liant à un Socket « socket », la couche application peut communiquer avec la couche transport via l'interface socket pour distinguer les communications des différents processus d'application ou connexions réseau, et implémenter des services simultanés pour la transmission de données.

Analyse du vocabulaire Sockets :

OptionsDescription
domainIndique la famille de protocoles utilisée, généralement PF_INET, PF_UNIX, PF_X25, etc.
typeSpécifiez le type de socket : SOCK_STREAM ou SOCK_DGRAM. L'interface Socket définit également le Socket d'origine (SOCK_RAW), permettant au programme d'utiliser des valeurs faibles. protocoles de niveau
protocoleGénéralement attribué une valeur de 0.
hostnameIdentifiant de l'interface réseau :
  • 选项描述
    domain指明所使用的协议族,通常为 PF_INET, PF_UNIX, PF_X25, 等等。
    type指定socket的类型:SOCK_STREAM 或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议
    protocol通常赋值0。
    hostname网络接口的标识符:
    • 字符串, 可以是主机名或IP地址

    • 字符串 "<broadcast>", 指定 INADDR_BROADCAST 地址。

    • 0 长度的字符串, 指定INADDR_ANY

    • 一个整数,解释为主机字节顺序的二进制地址。

    portport是端口的编号,每个服务器都会监听客户端连接的一个或多个端口号,一个端口号可以是 Fixnum 的端口号, 包含了服务器名和端口。
    String, Can être un nom d'hôte ou une adresse IP <🎜>
  • <🎜>La chaîne "<broadcast>", spécifie l'adresse INADDR_BROADCAST. <🎜>
  • <🎜>Une chaîne de longueur 0, spécifiant INADDR_ANY<🎜>
  • <🎜>Un entier interprété comme une adresse binaire dans l'ordre des octets de l'hôte. <🎜>
portport est le numéro du port Chaque serveur écoutera un ou plusieurs client. connexions. Plusieurs numéros de port, un numéro de port peut être un numéro de port Fixnum, y compris le nom du serveur et le port.

Client simple

Ci-dessous, nous écrivons une instance client simple avec un hôte et un port donnés. La classe Ruby TCPSocket fournit la méthode open pour ouvrir un socket.

TCPSocket.open(hosname, port) Ouvrez une connexion TCP.

Une fois que vous ouvrez une connexion Socket, vous pouvez la lire comme un objet IO, et lorsque vous avez terminé, vous devez fermer la connexion comme un fichier.

L'exemple suivant montre comment se connecter à un hôte spécifié, lire les données du socket et enfin fermer le 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

Service simple

Ruby You peut utiliser la classe TCPServer pour écrire un service simple. L'objet TCPServer est l'objet usine de TCPSocket.

Maintenant, nous utilisons TCPServer.open(hostname, port) pour créer un objet TCPServer.

Ensuite, appelez la méthode accept de TCPServer. Cette méthode attendra qu'un client se connecte au port spécifié, puis renverra un objet TCPSocket pour indiquer la connexion au 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                 # 关闭客户端连接
}

Maintenant, exécutez le code ci-dessus sur le serveur pour voir l'effet.


Service TCP multi-clients

Sur Internet, la plupart des services disposent d'un grand nombre de connexions client.

La classe Ruby's Thread facilite la création de services multithread, dans lesquels un thread effectue les connexions client tandis que le thread principal attend d'autres connexions.

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
}

Dans cet exemple, le socket s'exécute pour toujours, et lorsque server.accept reçoit une connexion du client, un nouveau thread est créé et commence immédiatement à traiter la demande. Le programme principal revient immédiatement en arrière et attend une nouvelle connexion.


Petit navigateur Web

Nous pouvons utiliser la bibliothèque de sockets pour implémenter n'importe quel protocole Internet. Le code suivant montre comment obtenir le contenu d'une page Web :

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                          # 输出结果

Pour implémenter un client de type Web, vous pouvez utiliser une bibliothèque prédéfinie pour HTTP telle que Net::HTTP.


Le code suivant est équivalent au code précédent :


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

Ci-dessus, nous présentons simplement brièvement l'application de socket dans Ruby, plus Pour en savoir plus documentation, veuillez consulter : Bibliothèque Ruby Socket et méthodes de classe