跳至內容

Berkeley插座

出自Taiwan Tongues 台語維基
這是此頁批准,以及是最近的修訂。

柏克萊插座(英語:Internet Berkeley sockets), 閣叫做BSD 插座( BSD sockets ) 是一種應用程式介面(API), 用佇網路插座(socket)佮 Unix 域插座,包括一个用 C 語言寫成的應用程式開發庫,主要用佇咧實現行程間通訊,佇電腦網路通訊方面被廣泛使用。

Berkeley 插座(也作 BSD 插座應用程式介面)拄開始是四配二 BSD Unix 作業系統(佇咧一千九百八十三發布)的一套應用程式介面。毋過,因為 AT & T 的專利保護著 UNIX,所以干焦佇一九八九年柏克萊大學才會當自由的發布家己的作業系統佮網路庫。

Berkeley 插座應用程式介面形成做事實上的網路插座的標準精髓。大多數其他的程式語言使用佮這套用 C 語言做的應用程式介面類似的介面。這套應用程式介面嘛予人用佇咧 Unix 域插座(Unix domain sockets), 後者會當佇單機頂懸做行程間通訊(IPC)的介面。

這種因為流的傳輸層的介面(TLI)為插座應用程式介面提供一種選擇。猶毋過,最近提供 TLI 應用程式介面的系統同時嘛提供 Berkeley 插座應用程式介面。

Berkeley 插座介面

Berkeley 插座介面,一个應用程式介面(API), 使用一个 Internet 插座的概念,使主機間抑是講一台電腦的行程間會當通訊。伊會當佇足濟無仝的輸入 / 輸出裝置佮驅動之上執行,就算講這片足有作業系統的具體實現。介面實現用於 TCP / IP 協定,因為按呢伊是維持 Internet 的基本技術之一。伊是由加利福尼亞的柏克萊大學開發,頭仔用佇咧 Unix 系統。現此時,所有的現代作業系統攏有一寡源於 Berkeley 插座介面的實現,伊已經成做連接 Internet 的標準介面。

插座介面的接入有三个無仝款的級別,上基礎的嘛是上有效的就是 raw socket 級別接入去。真少的應用程式需要佇外向通訊控制的這个級別接入去,所以乎 raw socket 級別是干焦用著開發電腦 Internet 相關技術的。最近幾年,大多數的作業系統已經實現矣對伊的全方位支援,包括講 Windows XP。

使用 Berkeley 插座的系統

因為 Berkeley 插座是頭一个 socket,大多數程式設計師足熟似的𪜶,所以大量系統共柏克萊插座做其主要的網路 API。一个無完整的列表如下:

  • Windows Sockets ( Winsock ),和 Berkeley Sockets 欲仝仔欲仝,上早是為著欲徙栽 Unix 程式。
  • Java Sockets
  • Python sockets
  • Perl sockets

標頭檔

Berkeley 插座介面的定義佇幾个標頭檔中。遮的檔案的名佮內容佮具體的實現之間有小可無仝款。大體上包括講:


` < sys / socket . h > `
核心 BSD 插座核心函式佮資料結構。


AF \ _ INET、AF \ _ INET 六位址集佮𪜶相應的協定集 PF \ _ INET、PF \ _ INET 六 . 廣泛用於 Internet,遮的包括著 IP 位址佮 TCP、UDP 埠號。


` < netinet / in . h > `
AF \ _ INET 和 AF \ _ INET 六位址家族佮𪜶對應的協定家族仔 PF \ _ INET 和 PF \ _ INET 六。佇網際網路編程中廣泛使用,包括講 IP 位址以及 TCP 和 UDP 埠號。


` < sys / un . h > `
PF \ _ UNIX / PF \ _ LOCAL 地址集。用佇執行佇一台電腦的程式間的本地通信,毋免佇咧網路通訊。


` < arpa / inet . h > `
處理數值型 IP 位址的函式。


` < netdb . h > `
共協定名佮主機名翻做數值位址的函式。揣在地資料猶閣有 DNS。

插座 API 函式

伊這列表是一个 Berkeley 插座 API 庫提供的函式抑是方法的概欲:

  • ` socket ( ) ` 建立一个新的確定類型的插座,類型用一个整型數值標識(檔案描述子), 閣替伊分配系統資源。
  • ` bind ( ) ` 一般用於侍服器捀,將一个插座佮一个插座位址結構相關聯,比如講,一个指定的埠頭佮 IP 位址。
  • ` listen ( ) ` 用於侍服器捀,共使一个結的 TCP 插座的 tcp 狀態由 CLOSE 轉到 LISTEN;作業系統核心為此監聽 socket 所做對應的 tcp 侍服器建立一个 pending socket 在列佮一个 established socket 在列;參數 backlog 指定 pending socket 在列的長度,零表示長度會當無限大。pending socket,就是某乜客戶捀三改握手的 syn 包到位,核心為這个 syn 包對應的 tcp 請求生成一个 socket(狀態為 SYN \ _ RECV), 三改握手閣無完成時的 socket。
  • ` connect ( ) ` 用佇咧客戶捀,為一个插座分配一个自由的本地埠頭。若是 TCP 插座的時陣,所以伊會試圖得著一个新的 TCP 連接。
  • ` accept ( ) ` 用於侍服器捀。伊接受一个對遠端客戶捀發出的建立一个新的 TCP 連接的接入請求,建立一个新的插座,佮該連接相應的插座位址相關聯。
  • ` send ( ) ` 和 ` recv ( ) ` , 抑是講 ` write ( ) ` 和 ` read ( ) ` , 抑是講 ` recvfrom ( ) ` 和 ` sendto ( ) ` , 用佇咧往爿 / 對遠端插座傳送佮接受資料。
  • ` close ( ) ` 用佇系統釋放分配予一个插座的資源。若是 TCP,連接會去予斷去。
  • ` gethostbyname ( ) ` 和 ` gethostbyaddr ( ) ` 用佇解析主機名佮位址。
  • ` select ( ) ` 用佇修整有如下情形的插座列表:準備讀,準備寫或者是有錯誤。
  • ` poll ( ) ` 用佇咧檢查插座的狀態。插座會用得予人測試,看有法度寫入去無、讀抑是有錯誤。
  • ` getsockopt ( ) ` 用佇查詢指定的插座一个特定的插座選項的當前值。
  • ` setsockopt ( ) ` 用佇指定的插座設定一个特定的插座選項。

較濟的細節如下共出。

socket ( )

` socket ( ) ` 為著通訊建立一个捀點,為插座返回一个檔案描述子。socket ( ) 有三个參數:

  • domain 為建立的插座指定協定集(抑是講號做位址族 address family )。比如講:
  • ` AF _ INET ` 表示 IPv 四網路協定
  • ` AF _ INET 六 ` 表示 IPv 六
  • ` AF _ UNIX ` 表示本地插座(用一个檔案)
  • type(socket 類型)如下:
  • ` SOCK _ STREAM `(可靠的一个面向流服務抑是流插座)
  • ` SOCK _ DGRAM `(資料報服務抑是資料報插座)
  • ` SOCK _ SEQPACKET `(可靠的連紲封包服務)
  • ` SOCK _ RAW ` ( 佇網路層之上家己指定運輸層協定頭,即原始插座 )
  • protocol 指定實際使用的傳輸協定。上捷看著的就是 ` IPPROTO _ TCP `、` IPPROTO _ SCTP `、` IPPROTO _ UDP `、` IPPROTO _ DCCP `。遮的協定攏佇咧 < netinet / in . h > 中有詳細說明。若這个該為講「` 零 `」的話,即根據選定的 domain 和 type 選擇使用預設協定。

若是發生錯誤,函式返回值為-一。抑無,函式會轉去一个代表新分配的描述符的整數。

原型:

bind ( )

` bind ( ) ` 為一个插座分配位址。當使用 ` socket ( ) ` 建立插座了後,干焦予伊所使用協定,並無分配位址。咧接受其他主機的連接前,著愛先呼叫 ` bind ( ) ` 為插座分配一个位址。` bind ( ) ` 有三个參數:

  • ` sockfd ` , 表示使用 bind 函式的插座描述符
  • ` my _ addr ` , 指向 sockaddr 結構(用於表示所分配位址)的指標
  • ` addrlen ` , 用 socklen \ _ t 欄位指定矣 sockaddr 結構的長度若是發生錯誤,函式返回值為-一,抑無替零。

原型

listen ( )

當 socket 佮一个位址結束結了後,` listen ( ) ` 函式會開始監聽可能的連接請求。毋過,這干焦會當佇有可靠資料流保證的時陣使用,比如講:資料類型 ( ` SOCK _ STREAM ` , ` SOCK _ SEQPACKET ` )。

listen ( ) 函式需要兩个參數:

  • ` sockfd ` , 一个 socket 的描述符仔 .
  • ` backlog ` , 完成三改握手、等待 accept 的全部接著的在列上大長度上限。對於 AF \ _ INET 類型的 socket,全連接數量做:min ( backlog , somaxconn )。當在列滿的時,新的攏連接會轉去錯誤。somaxconn 預設做一百二十八 . 半連接著列的最大長度可通過 sysctl 函式設定 tcp \ _ max \ _ syn \ _ backlog,預設值為兩百五十六。Linux Kernel 二嬸二了後,全部接在列佮半連接在列分別叫做 accept queue 佮 syns queue。根據 / proc / sys / net / ipv 四 / tcp \ _ abort \ _ on \ _ overflow 里的值為零表示若三擺握手第三步的時全連接佇咧列滿矣,遐爾 server 抨掉 client 發過來的 ack,server 過一段時間閣再傳送 syn + ack 給 client(也就是重新行握手的第二步), 若是 client 過時間等較短,就真容易異常;tcp \ _ abort \ _ on \ _ overflow 為一表示第三擺握手的時若做全連接佇列滿矣,server 傳送一个 reset 包予 client,表示講你廢掉這个握手過程佮這个連接。

若是連接受,轉去零表示成功,錯誤轉去-一。

原型:

accept ( )

做應用程式監聽來自其他主機的面對資料流的連接時,通過事件(比如講 Unix select ( ) 系統呼叫)共通知。著愛用 ` accept ( ) ` 函式初初化連接。` accept ( ) ` 為每一个連接創立新的插座並且監聽佇咧列中移除這个連接。伊使用如下參數:

  • ` sockfd ` , 監聽的插座描述符仔
  • ` cliaddr ` , 指向 sockaddr 結構體的指標,客戶機位址的資訊。
  • ` addrlen ` , 指向 ` socklen _ t ` 的指標,確定客戶機位結構體的大細。

倒轉來一座描述符,出錯返回-一。進一步的通批著愛通過這个插座。

Datagram 插座無要求用 accept ( ) 處理,因為接收方可能用監聽插座隨處理這个請求。

函式原型:

connect ( )

` connect ( ) ` 系統呼叫做一个插座設定連接,參數有檔案來講主機位址。

某一寡類型的插座是無連接的,大多數攏是 UDP 協定。對遮的插座,共接時按呢的:預設傳送佮接收資料的主機由予定的位址確定,會用得使用 send ( ) 和 recv ( )。 倒轉來-一表示出錯,零表示成功。

函式原型:

select ( )

  • 第一个參數 nfds:無路用,干焦為著佮柏克萊 Socket 相容提供。
  • 第二个參數 readfds:指定一个 Socket 陣列,select 檢查該陣列中的所有 Socket。若有成功倒轉來,著 readfds 中存囥的是符合『可讀性』條件的陣列成員(如緩衝區中有可讀的資料)。
  • 第三个參數 writefds:指定一个 Socket 陣列,select 檢查該陣列中的所有 Socket。若有成功倒轉來,著 writefds 中存囥的是符合『可寫姓』條件的陣列成員(包括連接成功)。
  • 第四个參數 exceptfds:指定一个 Socket 陣列,select 檢查該陣列中的所有 Socket。若有成功倒轉來,著 cxceptfds 中存囥的是符合『有各樣』條件的陣列成員(包括連接失敗)。
  • 第五个參數 timeout:指定 select 執行上長的時間,若佇咧 timeout 限定的時間內,readfds、writefds、exceptfds 中指定的 Socket 無一个符合要求,就轉去零。

getsockname ( ) 和 getpeername ( )

getsockname 函式來取得已經結束(可能是未呼叫 bind 的系統自動結束)的套介面本地協定位址。

getpeername 函式獲得佮指定套介面連接的遠端資訊(IP : PORT)。

gethostbyname ( ) 和 gethostbyaddr ( )

` gethostbyname ( ) ` 和 ` gethostbyaddr ( ) ` 函式是用來解析主機名佮位址的。可能可能可以用 DNS 服務抑是本地主機頂懸的其他解析機制(譬如講查詢 / etc / hosts)。 倒轉來一个指向 struct hostent 的指標,這个結構體描寫一个 IP 主機。函式使用如下參數:

  • name 指定主機名。比如講 www . wikipedia . org
  • addr 指向 struct in \ _ addr 的指標,包含主機的所在。
  • len 給出 addr 的長度,以位元組為單位。
  • type 指定位址族類型(比如講 AF \ _ INET)。

出錯返回 NULL 指標,會當通過檢查 h \ _ errno 來確定是臨時錯誤抑是未知主機。正確閣倒轉來一个有效的 struct hostent \ *。

遮的函式並毋是柏克萊插座嚴格的組成部份。遮的函式可能是過時去矣,干焦會當處理 IPv 四个址。佇咧 IPv 六中,替代的新函式是 getaddrinfo ( ) and getnameinfo ( ) , 遮新函式是因為 _ addrinfo _ 資料結構。參考 < Ws 二 tcpip . h >。

函式原型:

setsockopt ( )

setsockopt 函式用來設定插座選項。

參數:

  • sockfd : 插座
  • level : 協定層 SOL \ _ SOCKET / IPPROTO \ _ IP / IPPRO \ _ TCP
  • optname : 選項名每一个協定層攏有其固定的選項名
  • optval : 緩衝區 set 是講向將欲寄囥的位址,get 是指向目前存囥資訊的位址
  • optlen : 緩衝區大細長度佇咧 socket 層,有以下一寡選項 :
  • SO \ _ BROADCAST 允准傳送廣播資料 int
  • SO \ _ DEBUG         允准除錯                 int
  • SO \ _ DONTROUTE       無走揣路由               int
  • SO \ _ ERROR         得著插座的錯誤             int
  • SO \ _ KEEPALIVE       保持連接                 int
  • SO \ _ LINGER       延遲關起來連接               struct linger
  • SO \ _ OOBINLINE       紮外資料來囥入正常資料的流         int
  • SO \ _ RCVBUF       接收緩衝區大細             int
  • SO \ _ SNDBUF       傳送緩衝區大細             int
  • SO \ _ RCVLOWAT       接收緩衝區下限             int
  • SO \ _ SNDLOWAT       傳送慢衝區下限             int
  • SO \ _ RCVTIMEO       接收過時間                 struct timeval
  • SO \ _ SNDTIMEO       傳送超時間                 struct timeval
  • SO \ _ REUSERADDR     允准重用本地位址佮埠頭         int
  • SO \ _ TYPE         得著插座的類型             int
  • SO \ _ BSDCOMPAT       佮 BSD 系統足容             int

ioctlsocket

根據第二个參數的取值,設定 socket I / O 模式:

  • FIONBIO:允准設定 socket 為著阻塞抑是講阻塞:做第三个參數 argp 為零是阻塞模式,為非零是非常的阻塞模式。若是已經對一个套介面進行矣 WSAAsynSelect ( ) 操作,則任何用 ioctlsocket ( ) 來共套介面重新設定做阻塞模式的試圖將以 WSAEINVAL 失敗。為著共套介面重新設定做阻塞模式,應用程式著愛代先用 WSAAsynSelect ( ) 搧叫(IEvent 參數置做零)來禁至 WSAAsynSelect ( ) , 抑是通過設定 lNetworkEvents 參數為零來呼叫 WSAEventSelect。
  • FIONREAD:倒轉去插座 s 後一改自動讀入的資料量的大細。若確定講(determin)吊掛(pending)佇網路輸入緩衝區內底,會當對 socket s 中讀的資料總數。返回單次 recv 函式會當讀的資料的總數
  • SIOCATMARK:倒轉來所有的「緊急」(𤆬外)資料敢是攏已經讀入去矣。干焦適用佇咧 SOCK \ _ STREAM 類型的彼个套介面,而且這套介面已經予人設定做會當線頂接收帶外資料(SO \ _ OOBINLINE)

inet \ _ pton 佮 inet \ _ ntop

inet \ _ pton 佮 inet \ _ ntop 兩个函式,佇咧 ASCII 字元描述的 IP 位址佮網路位元組序的四位元組 IP 位址之間轉換。字母 " n " 佮 " p ",分別是 numerical 佮 presentation 的縮寫。

協定佮位址

插座 API 是 Unix 網路的通用介面,允准使用各種網路協定佮位址。

下跤出一寡例句,佇咧這馬的 Linux 和 BSD 中一般攏已經實現矣。

` ` ` PF _ LOCAL , PF _ UNIX , PF _ FILE Local to host ( pipes and file-domain ) PF _ INET IP protocol family PF _ AX 二十五 Amateur Radio AX . 二十五 PF _ IPX Novell Internet Protocol PF _ APPLETALK Appletalk DDP PF _ NETROM Amateur radio NetROM PF _ BRIDGE Multiprotocol bridge PF _ ATMPVC ATM PVCs PF _ X 二十五 Reserved for X . 二十五 project PF _ INET 六 IP version 六 PF _ ROSE Amateur Radio X . 二十五 PLP PF _ DECnet Reserved for DECnet project PF _ NETBEUI Reserved for 八百空二二 LLC project PF _ SECURITY Security callback pseudo AF PF _ KEY PF _ KEY key management API PF _ NETLINK , PF _ ROUTE routing API PF _ PACKET Packet family PF _ ASH Ash PF _ ECONET Acorn Econet PF _ ATMSVC ATM SVCs PF _ SNA Linux SNA Project PF _ IRDA IRDA sockets PF _ PPPOX PPPoX sockets PF _ WANPIPE Wanpipe API sockets PF _ BLUETOOTH Bluetooth sockets ` ` `

socket 的通用 address 來講結構 sockaddr 是一个十六位元組大細的結構(二 + 十四), sa \ _ family 會當認為講是 socket address family 的縮寫。另外的十四位元組是用來描述位址。當指定 sa \ _ family=AF \ _ INET 了後,sa \ _ data 的形式也就攏固定落來:上前捀的兩位元組用佇記錄十六位元的埠頭,紲落來的四位元組用於記錄三十二位元的 IP 位址,上尾的八个元組清空為零。

使用 TCP 的侍服器客戶機舉例

侍服器

設定一个簡單的 TCP 侍服器牽涉著列步:

  • 搧叫 socket 函式建立插座,應當使用的參數參見定式。
  • 搧叫 bind 函式共插座結來一个監聽埠頭。注意 bind 函式需要接受一个 sockaddr \ _ in 結構體成做參數,因此咧呼叫 bind 函式進前,程式愛先聲明一个 sockaddr \ _ in 結構體,用 memset 函式共伊清零,才閣共內底的 sin \ _ family 設定做 AF \ _ INET,紲落來伊,程式需要設定其實 sin \ _ port 成員變數,即監聽埠頭。需要說明的是,sin \ _ port 中的埠號需要用網路位元組序儲存,因此需要呼叫 htons 函式對埠號進行轉換(函式名是 " host to network short " 的縮寫)。
  • 搧叫 listen 函式,使該插座成做一个所在咧監聽狀態的插座。
  • 紲落來伊,侍服器會使通過 accept 函式接受客戶捀的連接請求。若無收著連接請求,accept 函式將袂倒轉去閣窒程式的執行。接收著連接請求了後,accept 函式會為著連接倒轉來一个插座描述符。accept 函式會當被濟濟擺呼叫來接受無仝客戶捀的連接請求,而且進前的連接猶原佇咧監聽狀態—— 一直到其實予人關起來為止。
  • 這馬乎,侍服器會使通過著 send,recv 抑是講對 write,read 等函式的呼叫來同客戶捀進行通批。
  • 對著一个無閣需要的插座,會用得使用 close 就按呢共關起來。Note that if there were any calls to ` fork ( ) ` , each process must close the sockets it knew about ( the kernel keeps track of how many processes have a descriptor open ) , and two processes should not use the same socket at once .

Python 實現:

客戶機

建立一个客戶機連接牽連以下步驟:

  • 搧叫 ` socket ( ) ` 建立插座。
  • 用 ` connect ( ) ` 連接著侍服器,類似侍服器捀的操作,將一个 sin \ _ family 設為 AF \ _ INET , sin \ _ port 設做侍服器的監聽埠(猶原愛用網路位元組序), sin \ _ addr 設做侍服器 IP 位址的(抑是愛用網路位元組序)的 sockaddr \ _ in 做參數傳入。
  • 用 ` send ( ) ` 和 ` recv ( ) ` 抑是講 ` write ( ) ` 和 ` read ( ) `進行通信。
  • 用 ` close ( ) ` 終止連接。若呼叫 ` fork ( ) ` , 每一个行程攏愛用 ` close ( ) `。

Python 實現:

使用 UDP 的侍服器客戶機舉例

使用者資料報協定(UDP)是一个無保證正確傳輸的無連接協定。UDP 封包可能會烏白序到位,大部份到或者是直接遺失。但是設計的負載比 TCP 細。

UDP 位址空間,嘛即是 UDP 埠頭,和 TCP 埠頭是無關係的。

侍服器

Code may set up a UDP server on port 七千六百五十四 as follows :

頂懸的無限迴圈用 recvfrom ( ) 接收予 UDP 埠七千六百五十四的封包。使用如下參數:

  • 指向緊取資料指標
  • 緊取大細啦
  • 標誌
  • 位址
  • 位址結構體大細項仝款的功能 Python 實現:

客戶機

用 UDP 封包傳送一个 " Hello World ! " 予位址一百二十七堵空 . 空七一(迴環位址), 埠七千六百五十四。

` buffer ` 指定欲傳送資料的指標,` buffer _ length ` 指定緊取內容的大細。

平平功能的 Python 實現:

參見

  • 電腦網路
  • Winsock

參考資料

The " de jure " standard definition of the Sockets interface is contained in the POSIX standard , known as :

  • IEEE Std . 一千空三孵一孵二千空一 Standard for Information Technology—Portable Operating System Interface ( POSIX ) .
  • Open Group Technical Standard : Base Specifications , Issue 六 , December 兩千空一 .
  • ISO / IEC 九千九百四十五 : 兩千空二

Information about this standard and ongoing work on it is available from the Austin website .

The IPv 六 extensions to the base socket API are documented in RFC 三千四百九十三 and RFC 三千五百四十二 .

外部連結

  • 手冊頁
  • accept ( 二 )
  • connect ( 二 )
  • Beej's Guide to Network Programming-兩千空七
  • Beej's Guide to Network Programming 正體中文版(zh-tw)-二千空一十四
  • Beej's Guide to Network Programming 簡體中文版(zh-cn)-二千空一十四
  • UnixSocket FAQ
  • Get system IP list-C + + Example
  • quick TCP-IP NetIntro with C examples
  • Porting Berkeley Socket programs to Winsock-Microsoft's documentation .
  • Programming UNIX Sockets in C-Frequently Asked Questions-九百九十六
  • Linux network programming-_ Linux Journal _ , 一千九百九十八本條目部份抑是全部內容出自以 GFDL 授權發佈的《自由線上電腦詞典》(FOLDOC)。