- Ruby 基礎
- Ruby - 首頁
- Ruby - 概述
- Ruby - 環境設定
- Ruby - 語法
- Ruby - 類和物件
- Ruby - 變數
- Ruby - 運算子
- Ruby - 註釋
- Ruby - IF...ELSE
- Ruby - 迴圈
- Ruby - 方法
- Ruby - 程式碼塊
- Ruby - 模組
- Ruby - 字串
- Ruby - 陣列
- Ruby - 雜湊表
- Ruby - 日期和時間
- Ruby - 範圍
- Ruby - 迭代器
- Ruby - 檔案 I/O
- Ruby - 異常
Ruby - 套接字程式設計
Ruby 提供了兩個級別的網路服務訪問。在低階,您可以訪問底層作業系統的基本套接字支援,這使您可以為面向連線和無連線協議實現客戶端和伺服器。
Ruby 還擁有提供對特定應用程式級網路協議(如 FTP、HTTP 等)的更高級別訪問的庫。
本章使您瞭解網路中最著名的概念——套接字程式設計。
什麼是套接字?
套接字是雙向通訊通道的端點。套接字可以在程序內、同一臺機器上的程序之間或不同大陸上的程序之間進行通訊。
套接字可以基於多種不同的通道型別實現:Unix 域套接字、TCP、UDP 等。套接字為處理常見傳輸提供了特定的類,以及用於處理其餘傳輸的通用介面。
套接字有自己的詞彙表 -
| 序號 | 術語和描述 |
|---|---|
| 1 | 域 將用作傳輸機制的協議族。這些值是常量,例如 PF_INET、PF_UNIX、PF_X25 等。 |
| 2 | 型別 兩個端點之間的通訊型別,通常對於面向連線的協議為 SOCK_STREAM,對於無連線的協議為 SOCK_DGRAM。 |
| 3 | 協議 通常為零,這可用於識別域和型別內協議的變體。 |
| 4 | 主機名 網路介面的識別符號 - 一個字串,可以是主機名、點分四段地址或冒號(可能還有點)表示法中的 IPv6 地址 字串“<broadcast>”指定 INADDR_BROADCAST 地址。 零長度字串,指定 INADDR_ANY,或 一個整數,解釋為主機位元組序中的二進位制地址。 |
| 5 | 埠 每個伺服器監聽一個或多個埠上的客戶端呼叫。埠可以是 Fixnum 埠號、包含埠號的字串或服務的名稱。 |
一個簡單的客戶端
在這裡,我們將編寫一個非常簡單的客戶端程式,它將開啟到給定埠和給定主機的連線。Ruby 類TCPSocket提供open函式來開啟這樣的套接字。
TCPSocket.open(hosname, port )開啟到hostname上的port的 TCP 連線。
開啟套接字後,您可以像任何 IO 物件一樣從中讀取。完成後,請記住關閉它,就像關閉檔案一樣。
以下程式碼是一個非常簡單的客戶端,它連線到給定的主機和埠,從套接字讀取所有可用資料,然後退出 -
require 'socket' # Sockets are in standard library hostname = 'localhost' port = 2000 s = TCPSocket.open(hostname, port) while line = s.gets # Read lines from the socket puts line.chop # And print with platform line terminator end s.close # Close the socket when done
一個簡單的伺服器
要編寫 Internet 伺服器,我們使用TCPServer類。TCPServer 物件是 TCPSocket 物件的工廠。
現在呼叫TCPServer.open(hostname, port函式為您的服務指定一個port並建立一個TCPServer物件。
接下來,呼叫返回的 TCPServer 物件的accept方法。此方法等待客戶端連線到您指定的埠,然後返回一個TCPSocket物件,該物件表示與該客戶端的連線。
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
client = server.accept # Wait for a client to connect
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
}
現在,在後臺執行此伺服器,然後執行上述客戶端以檢視結果。
多客戶端 TCP 伺服器
網際網路上的大多數伺服器都設計為能夠在任何時間處理大量客戶端。
Ruby 的Thread類使建立多執行緒伺服器變得容易。一個伺服器接受請求並立即建立一個新的執行執行緒來處理連線,同時允許主程式等待更多連線 -
require 'socket' # Get sockets from stdlib
server = TCPServer.open(2000) # Socket to listen on port 2000
loop { # Servers run forever
Thread.start(server.accept) do |client|
client.puts(Time.now.ctime) # Send the time to the client
client.puts "Closing the connection. Bye!"
client.close # Disconnect from the client
end
}
在此示例中,您有一個永久迴圈,當 server.accept 響應時,會立即建立一個新的執行緒並啟動它來處理剛剛接受的連線,使用傳遞到執行緒中的連線物件。但是,主程式會立即迴圈回並等待新的連線。
以這種方式使用 Ruby 執行緒意味著程式碼是可移植的,並且將在 Linux、OS X 和 Windows 上以相同的方式執行。
一個微型 Web 瀏覽器
我們可以使用套接字型檔來實現任何 Internet 協議。例如,這裡有一段程式碼用於獲取網頁的內容 -
require 'socket'
host = 'www.tutorialspoint.com' # The web server
port = 80 # Default HTTP port
path = "/index.htm" # The file we want
# This is the HTTP request we send to fetch a file
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 complete response
# Split response at first blank line into headers and body
headers,body = response.split("\r\n\r\n", 2)
print body # And display it
要實現類似的 Web 客戶端,您可以使用預構建的庫,如Net::HTTP,用於處理 HTTP。以下是執行與先前程式碼等效操作的程式碼 -
require 'net/http' # The library we need
host = 'www.tutorialspoint.com' # The web server
path = '/index.htm' # The file we want
http = Net::HTTP.new(host) # Create a connection
headers, body = http.get(path) # Request the file
if headers.code == "200" # Check the status code
print body
else
puts "#{headers.code} #{headers.message}"
end
請檢查類似的庫以使用 FTP、SMTP、POP 和 IMAP 協議。
進一步閱讀
我們為您提供了套接字程式設計的快速入門。這是一個很大的主題,因此建議您檢視Ruby 套接字型檔和類方法以查詢更多詳細資訊。