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編程的程序例子。

 

http://blog.163.com/jiams_wang/blog/static/30339149201242335530940/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM