「原創宣告:保留所有權利,禁止轉載」
最近看到一些資料,提到了在同一臺機器上程序間通訊的方式:unix 套接字。起初我還以為是 Socket 介面,因為用到了變數 SocketPath。後面經過 AI 助理翻譯,才知道原來這是我的知識盲區了。
現在趕緊把這塊知識補充上。
Unix 套接字簡介
Unix 套接字(Unix domain sockets)是一種用於同一主機上程序間通訊(IPC,Inter-Process Communication)的機制。與網路套接字不同,Unix 套接字不使用網路協議棧,因此效能更高。它們主要用於需要高效、低延遲的本地程序通訊場景。
Unix 套接字的型別
-
流套接字(SOCK_STREAM):
- 提供面向連線的、可靠的位元組流服務,類似於 TCP。
- 資料傳輸具有順序和可靠性保障。
-
資料包套接字(SOCK_DGRAM):
- 提供無連線的、訊息為單位的資料傳輸,類似於 UDP。
- 資料傳輸不保證順序和可靠性。
Unix 套接字的工作流程
伺服器端操作流程:
- 建立套接字:使用系統呼叫建立一個套接字檔案描述符。
- 繫結套接字:將套接字繫結到一個檔案系統路徑,類似於網路套接字繫結到 IP 地址和埠。
- 監聽連線:使套接字進入監聽狀態,準備接受客戶端連線。
- 接受連線:當有客戶端請求連線時,接受連線並建立一個新的套接字檔案描述符用於通訊。
- 通訊:透過讀寫操作在伺服器和客戶端之間傳輸資料。
- 關閉套接字:完成通訊後,關閉套接字並清理資源。
客戶端操作流程:
- 建立套接字:使用系統呼叫建立一個套接字檔案描述符。
- 連線到伺服器:使用系統呼叫連線到伺服器端的套接字路徑。
- 通訊:透過讀寫操作在客戶端和伺服器之間傳輸資料。
- 關閉套接字:完成通訊後,關閉套接字並清理資源。
優點和應用場景
優點:
- 高效:由於不涉及網路協議棧的處理,Unix 套接字具有更低的開銷和更高的效能。
- 安全:Unix 套接字只能在本地主機上使用,降低了網路攻擊的風險。
- 簡單:配置和使用比網路套接字更簡單,不需要考慮網路配置和防火牆等問題。
典型應用場景:
- 本地程序通訊:例如,系統服務之間或應用程式內部元件之間的通訊。
- 高效能服務:需要高效、低延遲的本地服務,例如資料庫服務(如 MySQL)。
- 容器間通訊:在容器化環境中,本地容器之間的通訊。
Unix 套接字是一種高效、可靠的本地程序間通訊機制,適用於需要低延遲和高效能的應用場景。它們透過檔案系統路徑進行標識和通訊,使用方便且配置簡單,是本地主機上程序通訊的重要工具。
Go 語言實現
下面來用 Go 語言實現一個基於 unix 的服務端和客戶端,並且模擬進行程序間的通訊。下期我們將會用 Java&Groovy 重新實現一遍。同時測試一下誇語音 unix 套接字程序間通訊。
服務端
// TestServer 測試服務端
//
// @Description: 測試服務端
// @param t
func TestServer(t *testing.T) {
if _, err := os.Stat(socketPath); err == nil {
os.Remove(socketPath) // 如果檔案存在,刪除檔案
}
listener, err := net.Listen("unix", socketPath) // 監聽,建立一個unix socket
if err != nil {
fmt.Println("監聽發生異常:", err)
return
}
defer listener.Close() // 關閉監聽
fmt.Println("服務啟動...")
for { // 迴圈
conn, err := listener.Accept() // 接收連線
if err != nil {
fmt.Println("接受資訊錯誤:", err)
return
}
go handleConnection(conn) // 處理連線
}
}
其中處理連線的方法內容如下:
// handleConnection 處理連線
//
// @Description: 處理連線
// @param conn
func handleConnection(conn net.Conn) {
defer conn.Close() // 關閉連線
buffer := make([]byte, 1024) // 建立一個緩衝區
n, err := conn.Read(buffer) // 讀取資料
if err != nil { // 如果讀取錯誤
fmt.Println("讀取錯誤:", err)
return
}
fmt.Printf("收到訊息: %s\n", string(buffer[:n])) // 列印接收到的資料
}
客戶端
客戶端程式碼比較簡單,實現了傳送訊息的功能。
// TestClient 測試客戶端
//
// @Description: 測試客戶端
// @param t
func TestClient(t *testing.T) {
conn, err := net.Dial("unix", socketPath)
if err != nil {
fmt.Println("撥號發生錯誤:", err)
return
}
defer conn.Close()
message := "Hello FunTester"
_, err = conn.Write([]byte(message))
if err != nil {
fmt.Println("寫入訊息錯誤:", err)
return
}
}
測試控制檯列印
經過多次傳送訊息,控制檯列印資訊如下:
服務啟動...
收到訊息: Hello FunTester
收到訊息: Hello FunTester
收到訊息: Hello FunTester
下期的 Java 和 Groovy 版本敬請期待!!!
- 2021 年原創合集
- 2022 年原創合集
- 2023 年原創合集
- 服務端功能測試
- 效能測試專題
- Java、Groovy、Go、Python
- 單元&白盒&工具合集
- 測試方案&BUG&爬蟲&UI 自動化
- 測試理論雞湯
- 社群風采&影片合集
如果覺得我的文章對您有用,請隨意打賞。您的支援將鼓勵我繼續創作!
打賞支援
暫無回覆。