國立台灣大學電機工程學系
網路與多媒體實驗

Socket Programming

何謂socket

從網路的角度來看,socket就是通訊連結的端點;從程式設計者的角度來看,socket提供了一個良好的介面,使程式設計者不需知道下層網路協定運作的細節便可以撰寫網路通訊程式。

Windows Socket是以實作於Berkeley Software Distribution(BSD, release 4.3)中的UNIX sockets為基礎所發展出來的一套API,其不僅支援TCP/IP,對於 XeroxR Network System (XNS),Digital Equipment Corporation's DECNet protocol,NovellR Corporation's Internet Packet Exchange/Sequenced Packed Exchange(IPX/SPX) 亦可以支援。此外也提供機器碼的相容性,因此在不同的作業系統上移植時並不需要做任何修改。

Windows Socket API是一套動態連結函式庫(DLL),即程式在編譯時期並不會和這些函式庫連結,而是等到執行期間才會呼叫這函式。

Sockets的分類

在TCP/IP架構下,sockets可分為下面兩類:

(1)Datagram sockets(connectionless)

資料在datagram sockets間是利用UDP封包傳送,因此接收端socket可能會收到次序錯誤的資料,且其中部分資料亦可能會遺失。

(2)Stream sockets(connection-oriented)

資料在stream sockets間是利用TCP封包來傳送,因此接收端socket可以收到順序無誤、無重覆、正確的資料。此外TCP傳送時是採資料流的方式,因在傳送時會所有資料會視情況被分割在數個TCP封包中。

主從式架構模型(Client/Server model)

每個網路應用程式都有一個通訊端點,一種端點是用戶端,另一種是伺服器。根據定義,用戶端會先送出第一個封包,由一個伺服器接收。在初步接觸後,用戶端和伺服器均能開始收送資料。

依據socket所提供的服務來將它分類,然而在用戶端和伺服器上的這兩個sockets必須是同一類才能互相通訊,也就是說,他們必須都是stream(TCP)或都是datagram(UDP)。用戶端的應用程式必須要能找到並識別伺服器的socket,而伺服器會將它的socket命名以讓用戶端識別,就TCP/IP而言,一個socket name包括了IP位址、連結埠編號、以及協定本身。用戶端可用Windows Sockets的名稱伺服函式來查到標準伺服器的連結埠編號,而如果知道伺服器的主機名,則可以Windows Sockets的主機名稱分析函式,來查得伺服器的IP。當用戶端socket成功地聯繫上伺服器端之socket後,這兩者便形成一個“結合”(association)。在此時,每個socket都可以由它的名字及對方的名字所形成的組合加以識別。這個結合包括五個要素:所用的協定、用戶端IP位址、用戶端連結埠號碼、伺服器端IP位址、伺服器端連結埠號碼。這個“結合”的觀念並不只是Windows Sockets程式設計的基礎,它也是一般網路通訊的重要觀念。在結合中的資訊可識別及引導封包通過網路,從這一端的程式傳至另一端。

所有的網路應用程式皆可分為五個步驟:

TCP Socket Connection

UDP Socket Connectoin

圖一 Socket程式簡圖

開啟一個Socket

Socket是通訊的端點,好比是電腦的網路介面卡,使得網路應用程式可以像介面卡插在主機板上一樣,插入網路中。一般說來你只會有一片網路卡在電腦中,但是你可以有許多sockets,而且它們也可以同時使用一片網路卡。用戶端與伺服器端都需要一個socket以存取網路資料,使用socket()函式呼叫就可開啟一個socket。(如圖一所示)

為Socket命名

伺服器端的程式必須為它的socket命名,這樣用戶端才能找到並正確地辨識出它的socket,如果伺服器沒有替它的socket命名,則協定堆疊會拒絕用戶端要通訊的請求。要幫socket取名必須設定三個參數:協定、連結埠號碼、及位址,而用戶端就要用這些值來和伺服器建立連結。要為socket命名,伺服器必須為socket位址結構設初始值並呼叫bind()函式,以指定本身連結埠號碼和IP位址,完成命名的工作。

與另一個Socket結合

假設我們在用戶端與伺服器端均開啟一個socket,並至少為伺服器端的socket命名。接下來伺服器要準備接收封包,而用戶端要準備發送封包,當此準備工作完成後,此兩端的sockets就叫建立一個”結合”(association)。如何為結合此兩端的socket做準備呢?在WinSock API中提供了幾個函式來完成此動作。在伺服器端則以呼叫listen()來準備接受用戶端送來的連結要求,如果收到連線要求,則開啟另一個新的socket來和用戶端進行連線(使用accept()函式);而在用戶端則是呼叫connect()函式與伺服器端的socket完成結合。

在Sockets間收送資料

此時我們已經在用戶端和伺服器的sockets間建立了結合,也就是說,我們已經可以開始收送資料了。如何收送資料呢?在一個已連結的socket上收送資料可呼叫recv()與send()來完成;而在一個無連結的socket上收送資料可呼叫recvfrom()與sendto()來完成。

關閉Socket

當用戶端完成收送資料且往後並不會在使用時,必須關閉socket,對TCP socket而言,關閉socket除了將socket的資源還給協定堆疊,此外並嘗試將以建立的連結關閉。但對UDP socket而言,則是單純地將資源還給協定堆疊。關閉socket可呼叫closesocket()來完成。


參考文獻

1. "INTERNETWORKING WITH TCP/IP VOL.3 CLIENT-SERVER PROGRAMMING AND APPLICATIONS Windows Sockets Version, ” Douglas E. Comer and David L. Stevens, Prentice-Hall International, Inc.

2. “Windows Sockets網路程式設計經典”,李孟書、黃鶴超譯,美商愛迪生衛斯理、碁峰資訊股份有限公司合作出版。

3. “WinSock網路程式設計之鑰”,黃俊堯、黃耀文、許景華、陳孝忠著,資訊人文化事業

 

 

©2010 網路與多媒體實驗室@國立台灣大學
Last Modified by Shih-Lung Chao, 2010/9/7