套接字(socket)是一個抽象層,應(yīng)用程序可以通過它發(fā)送或接收數(shù)據(jù),可對其進(jìn)行像對文件一樣的打開、讀寫和關(guān)閉等操作。套接字允許應(yīng)用程序?qū)/O插入到網(wǎng)絡(luò)中,并與網(wǎng)絡(luò)中的其他應(yīng)用程序進(jìn)行通信。網(wǎng)絡(luò)套接字是IP地址與端口的組合。1
簡述傳輸層實現(xiàn)端到端的通信,因此,每一個傳輸層連接有兩個端點。那么,傳輸層連接的端點是什么呢?不是主機,不是主機的IP地址,不是應(yīng)用進(jìn)程,也不是傳輸層的協(xié)議端口。2傳輸層連接的端點叫做套接字(socket)。根據(jù)RFC793的定義:端口號拼接到IP地址就構(gòu)成了套接字。所謂套接字,實際上是一個通信端點,每個套接字都有一個套接字序號,包括主機的IP地址與一個16位的主機端口號,即形如(主機IP地址:端口號)。例如,如果IP地址是210.37.145.1,而端口號是23,那么得到套接字就是(210.37.145.1:23)。1
總之,套接字Socket=(IP地址:端口號),套接字的表示方法是點分十進(jìn)制的IP地址后面寫上端口號,中間用冒號或逗號隔開。每一個傳輸層連接唯一地被通信兩端的兩個端點(即兩個套接字)所確定。2
套接字可以看成是兩個網(wǎng)絡(luò)應(yīng)用程序進(jìn)行通信時,各自通信連接中的一個端點。通信時,其中的一個網(wǎng)絡(luò)應(yīng)用程序?qū)⒁獋鬏數(shù)囊欢涡畔懭胨谥鳈C的Socket中,該Socket通過網(wǎng)絡(luò)接口卡的傳輸介質(zhì)將這段信息發(fā)送給另一臺主機的Socket中,使這段信息能傳送到其他程序中。因此,兩個應(yīng)用程序之間的數(shù)據(jù)傳輸要通過套接字來完成。2
在網(wǎng)絡(luò)應(yīng)用程序設(shè)計時,由于TCP/IP的核心內(nèi)容被封裝在操作系統(tǒng)中,如果應(yīng)用程序要使用TCP/IP,可以通過系統(tǒng)提供的TCP/IP的編程接口來實現(xiàn)。3在Windows環(huán)境下,網(wǎng)絡(luò)應(yīng)用程序編程接口稱作Windows Socket。為了支持用戶開發(fā)面向應(yīng)用的通信程序,大部分系統(tǒng)都提供了一組基于TCP或者UDP的應(yīng)用程序編程接口(API),該接口通常以一組函數(shù)的形式出現(xiàn),也稱為套接字(Socket)。1
發(fā)展Socket最初是加利福尼亞大學(xué)Berkeley分校為Unix系統(tǒng)開發(fā)的網(wǎng)絡(luò)通信接口。后來隨著TCP/IP網(wǎng)絡(luò)的發(fā)展,Socket成為最為通用的應(yīng)用程序接口,也是在Internet上進(jìn)行應(yīng)用開發(fā)最為通用的API。2
Windows系統(tǒng)流行起來之后,由Microsoft聯(lián)合了其他幾家公司在Berkeley Sockets的基礎(chǔ)之上進(jìn)行了擴充(主要是增加了一些異步函數(shù),并增加了符合Windows消息驅(qū)動特性的網(wǎng)絡(luò)事件異步選擇機制),共同制定了一套Windows下的網(wǎng)絡(luò)編程接口,即Windows Sockets規(guī)范。1Windows Sockets規(guī)范是一套開放的、支持多種協(xié)議的Windows下的網(wǎng)絡(luò)編程接口,包括1.1版和2.0版兩個版本。其中1.1版只支持TCP/IP協(xié)議,而2.0版可以支持多協(xié)議,2.0版有良好的向后兼容性。當(dāng)前Windows下的Internet軟件絕大部分都是基于Windows Socks開發(fā)的。2
分類為了滿足不同的通信程序?qū)νㄐ刨|(zhì)量和性能的要求,一般的網(wǎng)絡(luò)系統(tǒng)提供了三種不同類型的套接字,以供用戶在設(shè)計網(wǎng)絡(luò)應(yīng)用程序時根據(jù)不同的要求來選擇。這三種套接為流式套接字(SOCK-STREAM)、數(shù)據(jù)報套接字(SOCK-DGRAM)和原始套接字(SOCK-RAW)。1
(1)流式套接字。它提供了一種可靠的、面向連接的雙向數(shù)據(jù)傳輸服務(wù),實現(xiàn)了數(shù)據(jù)無差錯、無重復(fù)的發(fā)送。流式套接字內(nèi)設(shè)流量控制,被傳輸?shù)臄?shù)據(jù)看作是無記錄邊界的字節(jié)流。在TCP/IP協(xié)議簇中,使用TCP協(xié)議來實現(xiàn)字節(jié)流的傳輸,當(dāng)用戶想要發(fā)送大批量的數(shù)據(jù)或者對數(shù)據(jù)傳輸有較高的要求時,可以使用流式套接字。2
(2)數(shù)據(jù)報套接字。它提供了一種無連接、不可靠的雙向數(shù)據(jù)傳輸服務(wù)。數(shù)據(jù)包以獨立的形式被發(fā)送,并且保留了記錄邊界,不提供可靠性保證。數(shù)據(jù)在傳輸過程中可能會丟失或重復(fù),并且不能保證在接收端按發(fā)送順序接收數(shù)據(jù)。在TCP/IP協(xié)議簇中,使用UDP協(xié)議來實現(xiàn)數(shù)據(jù)報套接字。在出現(xiàn)差錯的可能性較小或允許部分傳輸出錯的應(yīng)用場合,可以使用數(shù)據(jù)報套接字進(jìn)行數(shù)據(jù)傳輸,這樣通信的效率較高。2
(3)原始套接字。該套接字允許對較低層協(xié)議(如IP或ICMP)進(jìn)行直接訪問,常用于網(wǎng)絡(luò)協(xié)議分析,檢驗新的網(wǎng)絡(luò)協(xié)議實現(xiàn),也可用于測試新配置或安裝的網(wǎng)絡(luò)設(shè)備。1
創(chuàng)建套接字以Berkeley Socket的一些基本的套接字系統(tǒng)調(diào)用為例。WinsockAPI也同樣具有這些調(diào)用。1
1.創(chuàng)建套接字 socket()任何用戶要進(jìn)行通信都必須創(chuàng)建套接字,創(chuàng)建套接字是通過系統(tǒng)調(diào)用socket()函數(shù)實現(xiàn)的。2
(1)socket()函數(shù)調(diào)用的格式:1
SOCKET PASCAL FAR socket(int af,int type,int protocol);(2)socket()函數(shù)的參數(shù):af,type,protocol。參數(shù)af指定套接字使用的協(xié)議族。也就是說,利用它來分辨地址的類型。UNIX支持的協(xié)議族有:UNIXDomain(AF_UNIX)、In-temet(AF_INET)、XeroxNS(AF_NS)等。而Dos和Windows僅支持AF_INET。1type參數(shù)指定所需的通信類型。包括數(shù)據(jù)流(SOCK_STREAM)、數(shù)據(jù)報(SOCK-DGRAM)和原始類型(S0CK_RAW)。參數(shù)protocol說明該套接字使用的協(xié)議族中的特定協(xié)議。如果調(diào)用者不希望特別指定使用的協(xié)議,則置為0,使用默認(rèn)的連接模式。2
(3)該函數(shù)調(diào)用成功,返回一個套接字描述符,該函數(shù)調(diào)用失敗,返回值為INVALID_SOCKET。2
關(guān)閉套接字當(dāng)對某個套接字的通信結(jié)束時,必須調(diào)用該函數(shù)關(guān)閉指定的套接字。2
函數(shù)格式:1
BOOL closesocket(SOCKETs);s是已結(jié)束通信任務(wù)要關(guān)閉的套接字的描述符。1
調(diào)用流程套接字調(diào)用流程如下圖所示。2
socket():創(chuàng)建套接字。2
bind():指定本地地址。一個套接字用socket()創(chuàng)建后,它其實還沒有與任何特定的本地或目的地址相關(guān)聯(lián)。在很多情況下,應(yīng)用程序并不關(guān)心它們使用的本地地址,這時就可以不用調(diào)用bind指定本地的地址,而由協(xié)議軟件為它們選擇一個。但是,在某個知名端口(Well-known Port)上操作的服務(wù)器進(jìn)程必須要對系統(tǒng)指定本地端口。所以一旦創(chuàng)建了一個套接字,服務(wù)器就必須使用bind()系統(tǒng)調(diào)用為套接字建立一個本地地址。1
connect():將套接字連接到目的地址。初始創(chuàng)建的套接字并未與任何外地目的地址關(guān)聯(lián)。客戶機可以調(diào)用connect()為套接字綁定一個永久的目的地址,將它置于已連接狀態(tài)。對數(shù)據(jù)流方式的套接字,必須在傳輸數(shù)據(jù)前,調(diào)用connect()構(gòu)造一個與目的地的TCP連接,并在不能構(gòu)造連接時返回一個差錯代碼。如果是數(shù)據(jù)報方式,則不是必須在傳輸數(shù)據(jù)前調(diào)用connect。如果調(diào)用了connect(),也并不像數(shù)據(jù)流方式那樣發(fā)送請求建連的報文,而是只在本地存儲目的地址,以后該socket上發(fā)送的所有數(shù)據(jù)都送往這個地址,程序員就可以免去為每一次發(fā)送數(shù)據(jù)都指定目的地址的麻煩。2
listen():設(shè)置等待連接狀態(tài)。對于一個服務(wù)器的程序,當(dāng)申請到套接字,并調(diào)用bind()與本地地址綁定后,就應(yīng)該等待某個客戶機的程序來要求連接。listen()就是把一個套接字設(shè)置為這種狀態(tài)的函數(shù)。1
accept():接受連接請求。服務(wù)器進(jìn)程使用系統(tǒng)調(diào)用socket,bind和listen創(chuàng)建一個套接字,將它綁定到知名的端口,并指定連接請求的隊列長度。然后,服務(wù)器調(diào)用accept進(jìn)入等待狀態(tài),直到到達(dá)一個連接請求。1
send()/recv()和sendto()/recvfrom():發(fā)送和接收數(shù)據(jù) 。在數(shù)據(jù)流方式中,一個連接建立以后,或者在數(shù)據(jù)報方式下,調(diào)用了connect()進(jìn)行了套接字與目的地址的綁定后,就可以調(diào)用send()和reev()函數(shù)進(jìn)行數(shù)據(jù)傳輸。1
closesocket():關(guān)閉套接字。1
本詞條內(nèi)容貢獻(xiàn)者為:
尚軼倫 - 副教授 - 同濟大學(xué)數(shù)學(xué)科學(xué)學(xué)院