董偉梁
摘要:套接字(SOCKET)的客戶端/服務器(c/s)的通信模型,是基于TCP/IP協(xié)議的一種通信方式。本文結合c/s模型和SOCKET工作原理,闡述了socket原理以及如何實現(xiàn)Linux系統(tǒng)下的面向連接的socket通信。
關鍵字:SOCKET C/S Linux TCP/IP
引言
網(wǎng)絡編程的特點就在于它從客戶端和服務器兩個方面出發(fā),具有監(jiān)聽、請求和連接三個過程。Linux與Unix十分相似,它不僅網(wǎng)絡功能非常強大,而且穩(wěn)定性高,很適合運用到網(wǎng)絡編程通信之中。SOCKET作為一種編程接口,在網(wǎng)絡協(xié)議和應用程序的聯(lián)系之中扮演者不可或缺的角色。
1 TCP/IP協(xié)議結構
TCP/IP協(xié)議由網(wǎng)絡層IP協(xié)議和運輸層TCP協(xié)議構成,是一種基本的網(wǎng)絡協(xié)議。其中IP協(xié)議管理互聯(lián)網(wǎng)設備的地址,TCP協(xié)議管理數(shù)據(jù)的傳輸。TCP/IP協(xié)議下,應用程序有兩種編程接口,傳輸層接口(TLI)和套接字接口(SOCKET)?,F(xiàn)如今,SOCKET接口已經(jīng)成為普遍認可的編程接口形式。
2 SOCKET通信原理與模型
SOCKET中文名稱套接字,是一種為適應TCP/IP程序開發(fā)而設計的一種接口形式。在一個具有兩端的通信進程中,一個套接字只能描述其中一端,所以需要其他套接字來描述另一端。
SOCKET在用于網(wǎng)絡通信時,取其幾個本意中“插座”的意思。套接字就好比是固定電話機和電話線之間的插座,或者說是接口。電話接口對應著一個的電話號碼,當乙使用電話機向甲尋求通話時,乙的電話機必須有一個確定的電話號碼,同時他也要知道甲的電話號碼。即至少在通信時雙方各擁有一個固定的SOCKET。這時如果甲處于空閑狀態(tài),那么他可以選擇接聽乙的來電,雙方之間的通話連接的得以建立。乙發(fā)出的信息是通過電話機處理后傳向甲的,同時他收到的信息也是經(jīng)過電話機接收和處理過的。整個過程總體如下:
(1)服務器和客戶端分別建立SOCKET接口。
(2)服務器處于監(jiān)聽狀態(tài)??蛻舳嗣枋龃B接服務器的SOCKET,發(fā)送連接請求。
(3)服務器作出相應,并返回端口號與SOCKET地址。連接建立。
在電話通話時,還存在一種特殊情況。在通話連接建立之后,是丙而不是甲接聽電話,那么乙就需要請求甲接聽電話。為了能夠區(qū)分端口,每個SOCKET都會有一個由系統(tǒng)分配的唯一的端口號。在實際SOCKET通信時,服務器中有多個軟件進程,當進程與一個端口相綁定后,系統(tǒng)就會把所要發(fā)給該進程的信息通過端口號定位到相應端口,再把信息準確無誤地發(fā)給相應進程。
SOCKET是為客戶端/服務器模型(C/S)而開發(fā)的。在這種模式下,客戶端的SOCKET并不是一定的,好比乙可以使用不同的終端來呼叫甲。然而服務器的SOCKET是固定的,同時對網(wǎng)絡中的每個客戶端來說,它的SOCKET是已知的。
c/s模型是一種最基本的SOCKET模型,根據(jù)不同的發(fā)起方向,可以分為面向無連接形式和面向連接形式。UDP協(xié)議用于面向無連接的通信形式,該協(xié)議提供盡最大努力的服務,但卻不具有一定的可靠性,只能通過超時報錯和重傳機制來維持數(shù)據(jù)傳輸?shù)恼_性,在網(wǎng)絡連接狀況良好時尚可,不能適應網(wǎng)絡惡劣的環(huán)境。而面向連接的通信采用TCP協(xié)議,它雖然相比UDP協(xié)議要耗費更多的資源,但在一定程度上維持了傳輸?shù)姆€(wěn)定性,比較能夠以適應各種網(wǎng)絡環(huán)境下的傳輸工作。
對于面向連接和面向無連接,套接字類型與之相對應分為以下兩種形式:
(1)流式套接字(SOCKSTREAM)。
提供面向連接的傳輸服務。傳輸過程穩(wěn)定性強,可靠性高,發(fā)生重復、丟失和損壞的坑能動性低,可以通過流量控制來把控傳輸,數(shù)據(jù)流服務對象多為連接上的應用。
(2)數(shù)據(jù)報套接口(SOCKDGARM)
提供面向無連接的傳輸服務。傳輸?shù)臄?shù)據(jù)以獨立的形式被包裝成數(shù)據(jù)包發(fā)送,可靠性較低,發(fā)生傳輸錯誤的概率較高。
3 Linux下的面向連接的SOCKET編程設計
面向連接的SOCKET即流式套接字,采用TCP協(xié)議?;竟ぷ鬟^程如圖1所示。
服務器: (1)使用socket()創(chuàng)建流式套接字。(2)通過bind()函數(shù)把相應網(wǎng)絡地址和套接字關聯(lián)起來。(3)使用listen()來監(jiān)聽發(fā)送到端口的請求。(4)用accept()接受連接請求。無連接請求時,服務器進程處于停滯狀態(tài),繼續(xù)等待客戶端。(5)連接建立后,新的流式套接字便會生成,這個套接字會與客戶端套接字關聯(lián),而原套接字繼續(xù)處于監(jiān)聽狀態(tài)。此時可通過read()和write()函數(shù)與客戶端通信。(6)使用close()可終止連接與服務。
客戶端:(1)使用socket()創(chuàng)建流式套接字。(2)通過connect()發(fā)送連接服務器請求。(3)連接建立后,可用read()和write()函數(shù)與服務器通信。(4)使用close()可終止連接與服務。
服務器和客戶端程序編寫完成后,使用Linux的程序編譯工具GCC和程序調試工具GDB分別對兩個程序進行處理。處理完成后,在兩個終端內分別運行客戶端程序和服務器程序,先令服務器處于監(jiān)聽狀態(tài),之后客戶端發(fā)送文本數(shù)據(jù),即可成功建立C/S連接。如圖2所示。
4 結束語
套接字作為一種主要的編程接口形式,掌握它的編寫和使用十分重要。由于套接字基于c/s通信模型,編程時需要編寫服務器和客戶端兩部分程序,來實現(xiàn)主機之間的可靠通信。
參考文獻
[1]李德水.基于SOCKET編程接口的網(wǎng)絡通信[J],渭南師范學院學報,2005(02): 69-71.
[2]歐軍,吳清秀,裴云,張洪,基于socket的網(wǎng)絡通信技術研究[J].網(wǎng)絡安全技術與應用,2011(07):19_21.
[3]夏玲,王偉平,客戶端與服務器端的Socket通信[J],電腦知識與技術,2009,5(04): 812813.