UNIX SOCKET編程簡介

UNIX SOCKET編程簡介

1  Layered Model of Networking

Socket 編程的層次模型如下圖所示,

1.JPG 

最上面是應用層,應用層下面的是 SOCKET API 層,再下面是傳輸層和網絡層…… 實際上, Sockets API 層並不是一個真正定義的網絡層次,但卻很好的描述了 Socket 編程所處的位置和所扮演的角色。

TCP 狀態轉換圖

2.JPG

2 .什麼是 SOCKET 

簡單的, Socket 可以被定義描述爲兩個應用通信通道的端點。一個 Socket 端點可以用 Socket 地址來描述, Socket 地址結構由 IP 地址,端口和使用協議組成( TCP or UDP )。

3.JPG

3  Socket 地址結構

網絡中以主機 IP 、端口以及使用的協議表明一個網絡應用。 UNIX Socket 將它們組成一個結構,統稱爲 SOCKET 地址結構。

3.1  IPv4 對應的 SOCKET 地址結構

通常也稱爲“網際 SOCKET 地址結構”,以“ socketaddr_in ”命名,定義在頭文件 <netinet/in.h> 中。

4.JPG

所涉及到的數據類型:

5.JPG

3.2  IPv6 對應的 SOCKET 地址結構

6.JPG

3.3   通用地址結構

 

當地址結構作爲傳遞給任何一個 SOCKET 函數的參數時,任意一個 Socket 函數必須能處理每一種地址結構,爲了解決這個問題,提出了使用通用套接口地址結構。當任何一個地址結構要作爲指針參數傳到套接口函數時,必須要顯示轉化爲通用地址結構。

 IPv4 應用中,使用的通用地址結構爲 struct sockaddr, 定義在 <sys/socket.h> 中,

7.JPG

例如:

8.JPG

 IPv6 中,提出了一種新的通用地址結構: struct sockaddr_storage 定義在<netinet/in.h>中。

9.JPG

struct sockaddr  struct sockaddr_storage 的區別

<!--[if !supportLists]-->a.<!--[endif]-->struct sockaddr_storage能提供嚴格的結構對齊

<!--[if !supportLists]-->b.  <!--[endif]-->struct sockaddr_storage能容納系統支持的更大的地址結構

3.4  Socket 地址結構的比較

a.JPG

4  Client/Server Model

Client/Server 的網絡通信模型是使用最廣最爲基礎的通信模型。在 Socket API 環境,其應用可以歸納爲:

b.JPG 

TCP 鏈接建立

根據 TCP/IP 協議,函數 connect() 激發 TCP 的三路握手過程。

客戶端給服務器一個 SYN(J) 信號,服務器返回一個 ACK(J+1); 然後服務器給客戶端一個 SYN(K), 客戶端也同樣給服務器一個 ACK(K+1) ,這樣就算 connect 成功。

注意:服務器返回的 SYN(K)  ACK(J+1) 是放在同一個分節中發給客戶端的,因此鏈路在建立連接時只用了三個分節,故稱爲三路握手。

c.JPG 

TCP 鏈接終止

TCP 用三個分節建立一個鏈接,而終止連接時需要四個分節。原因在於被動關閉鏈接一方需要關閉處理時間,因此ACK  FIN 不能同時發給主動關閉一方。

d.JPG 

主動關閉一方在收到 ACK 後,在等待被動關閉方發 FIN 消息這一狀態稱爲處於 TIME_WAIT 狀態。

5 Socket API 描述

5.1 創建套接字—— socket 函數

應用程序在使用套接字前,必須擁有一個套接字,系統調用 socket ()嚮應用程序提供

創建套接字的手段,其調用格式如下:

e.JPG 

參數 family 指定通信發生的區域, UNIX 系統支持的地址族有: AF_UNIX,AF_INET,AF_NS 等,而 DOS  WINDOWS 中僅支持 AF_INET ,它是網際網區域。因此,地址族與協議族相同。

參數 type 描述要建立的套接字的類型。參數 protocol 說明該套接字使用的特定協議,如果調用者不希望特別指定使用的協議,則置爲 0 ,使用默認的連接模式。根據這 3 個參數建立一個套接字,並將相應的資源分配給它,同時返回一個整型套接字號。因此, socket ()系統調用實際上指定了 " 協議 " 

f.JPG 

5.2 指定本地址—— bind 函數

一個套接字用 socket ()創建後,存在一個名字空間(地址族),但它沒有被命名。 Bind ()將套接字地址(包括本地主機地址和本斷口地址)與所創建的套接字號聯繫起來,即將,名字賦予套接字,以指定本地半相關。其調用格式如下:

g.JPG

參數 socketfd 是由 socket() 調用返回的並且未作連接的套接字描述符(套接字號)。參數 myaddr 是賦給套接字socketfd 的本地地址(名字),其長度可變,結構隨通信域的不同而不同。 addrlen 表明了 name 的長度。

進程可以把一個特定的 IP 地址捆綁到它的套接口上,但此 IP 地址必須是主機的一個接口。對於 TCP 客戶端,這就爲在此套接口上發送的 IP 數據包分配了源 IP 地址。對於服務器端,這樣做就限制了套接口只接收來自那些目的地址爲此 IP 地址的客戶鏈接。

對於 TCP ,調用函數 bind 可以指定一個端口號,指定一個 IP 地址,可以兩者都指定,也可以一個都不指定。對於服務器,一般指定衆所周知的端口號。而不指定具體的 IP 地址。如果 TCP 服務器不把地址綁到套接口上,那麼內核就把客戶所發 SYN 所在分組的目的 IP 地址作爲服務器的源 IP 地址。

若指定端口號爲 0 ,則調用函數 bind 時,內核選擇一個臨時端口;但若指定一個通配 IP 地址,則直到套接口以連接 (TCP) 或數據報已在套接口上發出 (UDP), 內核才選擇一個本地 IP 

注意到在第四部分圖中,客戶端並沒有調用 bind 函數,因爲對於客戶端來說,沒有必要指定具體的 IP 和端口,如果需要,內核會選擇一個源 IP 地址和一個臨時的端口。

h.JPG

5.3 connect 函數

TCP 客戶用 connect() 函數建立一個與 TCP 服務器的鏈接。 Connect ()的調用格式如下:

i.JPG

參數 socket 是欲建立連接的本地套接字描述符。參數 servaddr 指出說明對方套接字地址結構指針。對方套接字地址長度由 addrlen 說明。

根據 TCP 的狀態轉移圖,函數 connect 導致從 CLOSED 狀態 ( 調用函數 socket 創建套接口以後就一直處於此狀態 ) 轉到 SYN_SENT 狀態,若成功轉到 ESTABLISHED 狀態。如果函數 connect 失敗,則原先創建的套接口就不可再用,必須關閉。如要重新嘗試,必須重新調用 socket ,再 connect 

5.4 listen 函數

函數 listen 僅被 TCP 服務器調用,它做兩件事情:

<!--[if !supportLists]-->1.          <!--[endif]-->當函數socket創建一個套接口時,它被假設爲一個主動套接口,也就是說,它是一個將調用connect發起鏈接的客戶套接口。函數listen將未鏈接的套接口轉換成被動套接口,告訴內核應接受指向此套接口的鏈接請求。根據TCP狀態轉移圖,函數listen導致套接口狀態從CLOSED轉到LISTEN

<!--[if !supportLists]-->2.          <!--[endif]-->函數的第二個參數規定了內核爲此套接口排隊的最大鏈接個數。

j.JPG

一般而言,此函數應該在 socket  bind 之後,調用函數 accept 之前調用。

參數 backlog 的解析:

對於給定的監聽套接口 (listen 之後 ) ,內核要維護兩個隊列:一個是處於三次握手過程中(即客戶端調用 connect ,服務器端收到 SYN ,並返回 ACK  SYN 後,在等待客戶端的 ACK ),處於 SYN_RCVD 狀態;另一個是從 connect 成功,處於 ESTABLISHED 狀態。

兩個隊列之和不能超過 backlog 

k.JPG

5.5 accept 函數

Accept 函數由 TCP 服務器調用,從已完成連接隊列頭返回一個已完成的鏈接。若已完成隊列爲空,則進程睡眠(假定套接口爲缺省的阻塞方式)。用於使服務器等待來自某客戶進程的實際連接。

l.JPG

參數 cliaddr  addrlen 用來返回鏈接對方進程(客戶端)的協議地址。

若函數成功返回,返回值是一個由內核自動生成的全新的描述字,代表與客戶端的鏈接。當我們討論函數 accept 時,常把它的第一個參數稱爲監聽套接口描述字(由 socket 生成的描述字);把它的返回值稱爲已連接套接口描述字。

6 Reference

補上參考書目及一些好文章

1. Windows Sockets 網絡程序設計大全 
    適合於WinSock編程入門。
2. Unix Networking Programming 3rd ed  
    很經典的書呀,如果你學習Unix Socket編程,你必須買的,學習WinSock也有作用的,因爲WinSock是參考的Unix Socket。
3. Windows網絡編程技術
    講了Win2000下的WinSock編程,講了TCP/IP, Netbios, IPX/SPX, ATM等在Windows下的編程,有很多代碼,還有一個MS Platform SDK的東西,這可是很難得的。對了,還有QoS和Raw Socket編程的程序例子

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章