TCP/IP 協定與 Internet 網路:第八章 TCP Socket 程式介面 上一頁 下一頁
8-3 Socket 連接方式
利用 Socket 介面發展網路應用程式有:虛擬電路和電報傳輸兩個主要通訊模式,以下我們以 Client/Server 架構分別介紹兩種通訊模式。
8-3-1 虛擬電路模式
『虛擬電路』(Virtual Circuit)模式表示通訊雙方傳輸資料之前,必須先建立通訊鏈路,因此所採用的傳輸層為連接導向的 TCP 協定。圖 8-4 是利用 Socket 程式庫,使用 TCP 協定建立的 Client/Sever 模式之基本架構,圖中 Server 端,首先呼叫 socket() 開啟一個通訊端點,接下來以 bind() 設定連接之傳輸埠口,並以 listen() 功能呼叫設定該 Socket 通訊端點為聆聽狀態(Listen Mode),準備接收對方要求連線,最後呼叫 accept() 等待 Client 端的連線。同樣的,Client 端也以 socket() 呼叫建立通訊端點,並以 bind() 連接到傳輸埠口,此時 Client 便可用 connect() 功能呼叫要求連接到 Server 端。雙方連線成功之後,便可以用 read() 和 write() 來互相傳輸資料,最後以 close() 結束此連線。
圖 8-4 Socket 的虛擬電路模式
在虛擬電路中有:同步(Synchronous)和非同步(Asynchronous)兩種傳輸模式。同步傳輸模式表示執行 Socket 程式後,還未得到回應時,會繼續等待一直到有回應才會回主程式,因此又稱為『阻斷模式』(Blocking Mode)。譬如,Server 端執行 accept() 程式,會一直等待到有連線到達,才會回應給主程式;而非同步模式表示執行 Socket 程式會即時回應給主程式,不論是否取得資料,又稱為『非阻斷模式』(Nonblocking Model)。
另一種情況,在同步傳輸模式中執行 read() 程式,如果接收緩衝器上有資料,便會直接讀取並返回主程式,但如果緩衝器上沒有資料,則會一直等待到連線對方傳送資料過來,才會返回主程式。非同步傳輸模式則不然,不論緩衝器上是否有資料可以讀取,都會即時返回主程式。由此可以見,同步傳輸只適合一對一的通訊端點傳輸,但大部分的 Client/Server 架構,Server 端必須能同時接受多個 Client 端的要求連線,同步傳輸便不適合。一般開啟連接導向的通訊端點,內定值都是同步傳輸模式,如果通訊端點欲能夠接受多點連接(一般都是 Server 端),必須將 Socket 設定為非同步傳輸模式。又從另一觀點來看,執行 read() 程式時,是由緩衝器上讀取資料,Socket ID 也如同一般檔案識別碼一樣,因此我們可以利用一般檔案控制程式 fcntl() 來設定。因此設定 Socket 為非同步傳輸模式的方法非常簡單,開啟 Socket 後,以 fcntl() 程式將 FNDELAY 旗號加入到 Socket ID(sd)內即可,程式格式如下:
如欲將 Socket 由非同步傳輸模式改為同步傳輸模式,也就是將旗號 FNDELAY 消除,其程式格式如下:
int flags;
flags = fcntl(sd, F_GETFL, 0); fcntl(sd, F_SETFL, (flags & ~FNDELAY)); |
參數 sd 為 Socket ID,第一個 fcntl() 程式是讀取 Socket 上的旗號值,而第二個 fcntl() 是作為取消 FNDELAY 旗號使用。
當 Socket 被設定成非同步傳輸模式之後,必須能夠隨時接收到資料的到達,以下有兩種方法:
(1) 週期性的執行 read() 功能呼叫,隨時準備接收及時到達之資料。
(2) 設定 Socket 具有發送訊息的功能,譬如,當一般資料到達時,會發送 SIGIO 訊號給主程式,再由主程式執行 read() 程式來讀取,或當快速資料(Expedited Data)到達時,會發送給 SIGURG 給主程式。
8-3-2 電報傳輸模式
圖 8-5 為建立在 UDP 協定上的『電報傳輸』(Datagram)模式,也是 Client/Server 的基本架構。Server 和 Client 端分別以 socket() 功能呼叫開啟通訊端點,並以 bind() 連結到傳輸埠口位址,其中 Client 端是否執行 bind() 為選項項目。雙方以 recvfrom() 和 sendto() 互相傳送資料。
圖 8-5 Socket 的電報傳輸模式
由圖 8-5 中表示,電報傳輸的預定值也是同步傳輸模式,也就是說,當某一方執行 recvfrom() 時,必需等待到收到對方傳送過來資料,才會返回到主程式,否則會一直等待著(Blocking Model)。如同虛擬電路一樣,我們可以利用 fcntl() 將其設定成非同步傳輸模式,程式格式如下:
fcntl(sd, F_SETFL, FNDELAY) |
參數 sd 是 Socket 的識別碼,可以是 Server 端或 Client 端。取消 FNDELAY 也如同虛擬電路一樣,不再另述。