通訊端與網路程式設計

Berkeley 通訊端 API(Berkeley socket API)

/ BERK-lee /

假設你想讓兩台不同電腦上的程式對話。與其為每個程式都發明一套新做法,作業系統給你一組標準的函式呼叫——開啟連線、寫入一些位元組、讀取一些位元組、關閉——用起來很像在操作檔案。這組標準就是 Berkeley 通訊端 API。它大約在 1983 年為 Berkeley Unix 系統而生,後來被廣泛複製(Linux、macOS、Windows,幾乎所有系統),如今成了程式接觸網路時近乎通用的方式。

具體來說,這個 API 給你一個通訊端(socket)——一個編號的代號,很像檔案描述符(file descriptor)——代表一段網路對話的一端。你先用 socket() 向核心要一個通訊端,然後在它上面呼叫一小組函式。對 TCP 伺服器,順序是 socket、bind(占用一個連接埠)、listen(宣告願意接受連線)、accept(接下一位來客)。對 TCP 用戶端則是 socket 再 connect。連上之後,雙方用 send/recv(或檔案風格的 write/read)搬資料,做完就 close。UDP 用同一個 socket() 呼叫,但跳過建立連線,改用 sendto/recvfrom。困難的部分(TCP 的可靠性、重送、排序)由核心在底下處理;你的程式只管讀寫位元組。

為什麼重要:你用過的幾乎每個網路程式——瀏覽器、收信程式、遊戲伺服器、資料庫——不是直接、就是透過包裝它們的高階函式庫,建立在這十來個呼叫之上。學會通訊端 API,就是學會抽象協定變成執行程式碼的那道接縫。一個誠實的提醒:這個 API 對 TCP 和 UDP 給你相同的呼叫,但底下的保證完全不同,所以寫出正確的網路程式碼,意味著要理解協定做了什麼,而不只是該呼叫哪個函式。

用白話步驟寫的最小 TCP 用戶端:fd = socket(AF_INET, SOCK_STREAM, 0);connect(fd, server_addr);send(fd, "GET / HTTP/1.0\r\n\r\n");recv(fd, buffer);close(fd)。整段對話就是這樣——請求出去、回應進來。

幾乎所有網路軟體底下都是這同一小撮呼叫。

通訊端描述符看起來像檔案,但它不是一般檔案:網路讀取可能回傳比你要求更少的位元組、可能阻塞、可能在串流途中以磁碟讀取通常不會的方式失敗。把它當成普通檔案處理,是經典的臭蟲來源。

又稱
BSD socketsPOSIX socketssocket API通訊端 API套接字 API