Unix Socket編程簡介

閱讀本文需要對TCP有基本的瞭解,對TCP連接的建立、斷開,以及TCP運行過程中狀態轉換不瞭解的童鞋可以首先閱讀我的另一篇博客:

http://blog.csdn.net/jiwang1990/article/details/39234757

Unix/Linux操作系統暴露給應用層的網絡編程接口是Socket,下面我們對Socket編程進行個簡單的介紹;Client/Server編程模型是使用最廣泛的編程模型,其過程如下圖所示:

下面我們將這幅圖中的相關函數調用映射到TCP連接的建立和斷開過程中:



Socket API概述

1創建套接字——socket函數

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

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

e.JPG

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

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

f.JPG

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

3 connect 函數

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

i.JPG

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

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

4 listen 函數

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

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

2. 函數的第二個參數規定了內核爲此套接口排隊的最大鏈接個數

j.JPG

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

參數 backlog 的解析:

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

兩個隊列之和不能超過 backlog 。

k.JPG

5 accept 函數

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

l.JPG

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

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


本文後半部分均爲轉載,原文地址爲:http://www.cnitblog.com/tarius.wu/articles/434.html

發佈了65 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章