段 哲 韓順鋒 黃 巍 丁忠義
(中國(guó)船舶重工集團(tuán)公司第七二二研究所 武漢 430079)
一般來(lái)說(shuō),對(duì)于 Winsock連接,無(wú)論是使用TCP協(xié)議還是UDP協(xié)議,客戶端程序連接服務(wù)端程序時(shí)無(wú)一例外的要指定IP地址(或機(jī)器名)和端口號(hào),那么,在端口已知而服務(wù)端程序所在機(jī)器地址或名稱未知的情況下,怎樣實(shí)現(xiàn)客戶端程序發(fā)起并建立連接呢?這就是本文需要解決的問題。
TCP(T ransfer Control Protocol)協(xié)議是一種面向連接的,可靠的傳輸層協(xié)議,可以將它同電話系統(tǒng)相比。面向連接是指一次正常的TCP傳輸需要通過在TCP客戶端和TCP服務(wù)端建立特定的虛電路連接來(lái)完成,該過程通常被稱為“三次握手”。在開始數(shù)據(jù)傳輸之前,用戶必須先建立連接。
如果應(yīng)用程序要使用TCP協(xié)議,那么首先必須決定應(yīng)用程序是服務(wù)器還是客戶端。如果要?jiǎng)?chuàng)建一個(gè)服務(wù)器端,那么應(yīng)用程序需要“監(jiān)聽”指定的端口。當(dāng)客戶端提出連接請(qǐng)求時(shí),服務(wù)器端能夠接受請(qǐng)求并建立連接。在連接建立之后,客戶端與服務(wù)器端可以自由地互相通訊。
UDP(User Datagram Protocol)協(xié)議是一種無(wú)連接協(xié)議,與TCP操作不同,兩臺(tái)計(jì)算機(jī)之間的傳輸類似于傳遞郵件:消息從一臺(tái)計(jì)算機(jī)發(fā)送到另一臺(tái)計(jì)算機(jī),不與對(duì)方建立連接,而是直接就把數(shù)據(jù)包發(fā)送過去。
另外,單次傳輸?shù)淖畲髷?shù)據(jù)量取決于具體的網(wǎng)絡(luò)。同時(shí),一個(gè)UDP應(yīng)用可同時(shí)作為應(yīng)用的客戶或服務(wù)器方。
由于UDP協(xié)議并不需要建立一個(gè)明確的連接,因此建立UDP應(yīng)用要比建立TCP應(yīng)用簡(jiǎn)單得多。
TCP協(xié)議和UDP協(xié)議各有所長(zhǎng)、各有所短,適用于不同要求的通信環(huán)境。TCP協(xié)議和 UDP協(xié)議之間的差別如表1所示。
本文提出了一種解決引言部分提出的問題的方案,該方案巧妙地將TCP與UDP結(jié)合起來(lái),利用其各自的優(yōu)點(diǎn),解決客戶端自動(dòng)查找并連接服務(wù)器端的問題,簡(jiǎn)單概括起來(lái)就是:客戶端首先使用UDP協(xié)議自動(dòng)查找服務(wù)器,然后用TCP協(xié)議和服務(wù)器建立連接。
當(dāng)客戶端程序啟動(dòng)以后,采用UDP協(xié)議發(fā)送廣播消息,廣播IP地址為255.255.255.255,端口1000,那么網(wǎng)絡(luò)內(nèi)所有機(jī)器的端口1000都能接收到該廣播消息。廣播消息的格式如表2所示。
表2 客戶端廣播消息格式(頭+ClientIP)
客戶端發(fā)送廣播消息的同時(shí),利用UDP協(xié)議監(jiān)聽1001端口。
在服務(wù)器端程序中,則要從廣播消息里獲得客戶端的IP地址,然后將本機(jī)IP改為和接收到的IP同一網(wǎng)段的不同IP,接著啟動(dòng)TCP服務(wù)器,再采用UDP協(xié)議將自己的IP地址發(fā)送到客戶端,讓客戶端與自己建立連接。
服務(wù)器端首先采用 UDP協(xié)議,監(jiān)聽端口1000,接受到廣播消息以后,就按表2定義的格式進(jìn)行解析。如果接收到的包長(zhǎng)為 30,就判斷前20Byte是否為“Apply for Connection”,如果匹配成功,則取得包內(nèi)后續(xù)的IP地址。將服務(wù)器地址更改為和客戶端同網(wǎng)段的不同的IP。例如接收到的包是“Apply for Connection192.168.0.88” ,那么服務(wù)器IP改為“192.168.0.223”。服務(wù)器IP更改以后,啟動(dòng)TCP服務(wù)器,將TCP協(xié)議端口綁定為1002。然后采用 UDP協(xié)議向客戶端發(fā)送服務(wù)器的IP(格式如表3),UDP協(xié)議的連接IP地址為接收到的IP,連接端口為1001。
表3 服務(wù)器響應(yīng)廣播消息格式(頭+ServerIP)
客戶端發(fā)送廣播消息以后,在1001端口接收到服務(wù)器端傳回的 IP以后,就和服務(wù)器端建立TCP連接,端口為1002。
服務(wù)器與客戶端主要連接流程圖如圖1所示。
圖1 客戶端自動(dòng)查找服務(wù)器并和服務(wù)器建立連接
考慮到編程的效率,本文采用VB 6.0實(shí)現(xiàn)了上面的方案。利用WinSock控件可以與遠(yuǎn)程計(jì)算機(jī)建立連接,Winsock包含有UDP協(xié)議和TCP協(xié)議,可用這兩種協(xié)議來(lái)建立客戶與服務(wù)器應(yīng)用程序來(lái)進(jìn)行數(shù)據(jù)交換,而且不必了解TCP/IP協(xié)議的細(xì)節(jié),只需要弄明白其屬性設(shè)置和方法的應(yīng)用即可。
在窗口中添加三個(gè)Winsock控件,第一個(gè)命名為sockgetdata,采用 UDP協(xié)議,將端口綁定為1000,用于接收廣播消息;第二個(gè)命名為sockudpsend,采用 UDP 協(xié)議,RemotePort為 1001,向客戶端發(fā)送服務(wù)器地址;第三個(gè)命名為sockTcpS-erver,采用 TCP協(xié)議,LocalPort為1002,用于和客戶端建立連接。
可在窗口中添加三個(gè)Winsock控件,第一個(gè)命名為 sockLink,采用 UDP協(xié)議,RemotePort為1000,發(fā)送廣播消息;第二個(gè)命名為 sockGetRemotIP,采用 UDP協(xié)議,將端口綁定為1001,接受服務(wù)器地址;第三個(gè)命名為sockTcpClient,采用TCP協(xié)議,LocalPort為1002,用于和服務(wù)器端建立連接。具體程序如下:
本文將TCP與UDP協(xié)議聯(lián)合起來(lái),提供了一種在端口已知而服務(wù)端程序所在機(jī)器地址或名稱未知的情況下,怎樣實(shí)現(xiàn)客戶端程序發(fā)起并建立連接的解決方案。此方法不僅提供了連接的方便實(shí)用性,而且保證了數(shù)據(jù)通信系統(tǒng)的高可靠性。
[1]Anthony Jones and Jim Ohlund.Microsoft Windows網(wǎng)路程式設(shè)計(jì)[M].2005,6
[2]Microsoft Corporation.Visual Basic 6.0中文版程序員指南[M].北京:北京希望電腦公司,1998
[3]W.RICHARD STEVENS BILL FENNER.UNIX網(wǎng)絡(luò)編程[M].楊繼張,譯
[4][美]W.Richard Stevens Stephen A.Rago.UNIX環(huán)境高級(jí)編程[M].第二版.尤晉元,張亞英,戚正偉,譯
[5][美]K.Wall,M >W(wǎng)atson,M.Whitis,et al.GNU/Linux編程指南[M].王勇,王一川,林花軍,等譯.北京:清華大學(xué)出版社,2000,7
[6]高傳善,錢松榮,毛迪林.數(shù)據(jù)通信與計(jì)算機(jī)網(wǎng)絡(luò)[M].北京:高等教育出版社,2000,7