Pengaturcaraan soket Ruby


Ruby menyediakan dua tahap akses kepada rangkaian Di peringkat bawah anda mempunyai akses kepada sistem pengendalian, yang membolehkan anda melaksanakan pelanggan dan pelayan dengan sokongan soket asas untuk protokol berorientasikan sambungan dan tanpa sambungan.

Ruby menyokong protokol rangkaian aplikasi secara seragam, seperti FTP, HTTP, dsb.

Sama ada di bahagian atas atau di bahagian bawah. Ruby menyediakan beberapa kelas asas yang membolehkan anda berinteraksi menggunakan TCP, UDP, SOCKS dan banyak protokol lain tanpa perlu melekat pada lapisan rangkaian. Kelas ini juga menyediakan kelas pembantu yang membolehkan anda membaca dan menulis dengan mudah ke pelayan.

Seterusnya mari kita belajar cara memprogramkan Ruby Socket


Apakah itu Soket

Apabila lapisan aplikasi menyampaikan data melalui lapisan pengangkutan, TCP dan UDP akan Menghadapi isu dengan servis berbilang proses aplikasi serentak pada masa yang sama. Berbilang sambungan TCP atau berbilang proses aplikasi mungkin perlu menghantar data melalui port protokol TCP yang sama. Untuk membezakan proses aplikasi dan sambungan yang berbeza, banyak sistem pengendalian komputer menyediakan antara muka yang dipanggil soket untuk interaksi antara aplikasi dan protokol TCP/IP untuk membezakan komunikasi rangkaian dan sambungan antara proses aplikasi yang berbeza.

Menghasilkan soket dengan tiga parameter utama: alamat IP destinasi komunikasi, protokol lapisan pengangkutan yang digunakan (TCP atau UDP) dan nombor port yang digunakan. Maksud asal Soket ialah "soket". Dengan menggabungkan ketiga-tiga parameter ini dan mengikatnya kepada Soket "soket", lapisan aplikasi boleh berkomunikasi dengan lapisan pengangkutan melalui antara muka soket untuk membezakan komunikasi daripada proses aplikasi atau sambungan rangkaian yang berbeza, dan melaksanakan perkhidmatan serentak untuk penghantaran data.

Analisis perbendaharaan kata soket:

OptionsPenerangan
domainMenunjukkan keluarga protokol yang digunakan, biasanya PF_INET, PF_UNIX, PF_X25, dsb.
jenisNyatakan jenis soket: SOCK_STREAM atau SOCK_DGRAM Antara muka Soket juga mentakrifkan Soket asal (SOCK_RAW), membenarkan atur cara menggunakan rendah -protokol peringkat
protokolBiasanya diberikan nilai 0.
nama hosPengecam antara muka rangkaian:
  • 选项描述
    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 menjadi nama hos atau alamat IP <🎜>
  • <🎜>Rentetan "<broadcast>", menentukan alamat INADDR_BROADCAST. <🎜>
  • <🎜>Rentetan 0-panjang, menyatakan INADDR_ANY<🎜>
  • <🎜>Integer yang ditafsirkan sebagai alamat binari dalam susunan bait hos. <🎜>
portport ialah nombor port Setiap pelayan akan mendengar satu atau lebih klien sambungan. Berbilang nombor port, satu nombor port boleh menjadi nombor port Fixnum, termasuk nama pelayan dan port.

Pelanggan ringkas

Di bawah kami menulis contoh klien mudah dengan hos dan port yang diberikan Kelas Ruby TCPSocket menyediakan kaedah terbuka untuk membuka soket.

TCPSocket.open(nama hos, port) Buka sambungan TCP.

Sebaik sahaja anda membuka sambungan Soket, anda boleh membacanya seperti objek IO, dan apabila anda selesai, anda perlu menutup sambungan seperti fail.

Contoh berikut menunjukkan cara menyambung ke hos yang ditentukan, membaca data daripada soket dan akhirnya menutup soket:

require 'socket'      # Sockets 是标准库

hostname = 'localhost'
port = 2000

s = TCPSocket.open(hostname, port)

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

Perkhidmatan ringkas

Ruby You boleh menggunakan kelas TCPServer untuk menulis perkhidmatan mudah. Objek TCPServer ialah objek kilang TCPSocket.

Kini kami menggunakan TCPServer.open(hostname, port) untuk mencipta objek TCPServer.

Seterusnya, panggil kaedah terima TCPServer Kaedah ini akan menunggu sehingga klien menyambung ke port yang ditentukan, dan kemudian mengembalikan objek TCPSocket untuk menunjukkan sambungan kepada klien.

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                 # 关闭客户端连接
}

Sekarang, jalankan kod di atas pada pelayan untuk melihat kesannya.


Perkhidmatan TCP berbilang pelanggan

Di Internet, kebanyakan perkhidmatan mempunyai bilangan sambungan pelanggan yang banyak.

Kelas Ruby's Thread memudahkan untuk membuat perkhidmatan berbilang benang, di mana satu utas melakukan sambungan pelanggan sementara utas utama menunggu lebih banyak sambungan.

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
}

Dalam contoh ini, soket berjalan selama-lamanya, dan apabila server.accept menerima sambungan daripada klien, urutan baharu dibuat dan mula memproses permintaan dengan serta-merta. Program utama serta-merta berputar semula dan menunggu sambungan baharu.


Pelayar Web Kecil

Kami boleh menggunakan perpustakaan soket untuk melaksanakan sebarang protokol Internet. Kod berikut menunjukkan cara untuk mendapatkan kandungan halaman 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                          # 输出结果

Untuk melaksanakan klien seperti web, anda boleh menggunakan perpustakaan pra-bina untuk HTTP seperti Net::HTTP.


Kod berikut adalah bersamaan dengan kod sebelumnya:


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

Di atas kami hanya memperkenalkan secara ringkas aplikasi soket dalam Ruby, lebih lanjut Untuk lebih lanjut dokumentasi, sila lihat: perpustakaan Ruby Socket dan kaedah kelas