杜曉春,劉婉妮,王 宏
(西安歐亞學(xué)院,710065)
TCP/IP協(xié)議(Transmission Control Protocol/Internet Protocol),是Internet最基本的協(xié)議,也是Internet的基礎(chǔ)。它并不是只包括TCP(傳輸控制協(xié)議)和IP(網(wǎng)際協(xié)議)這兩個(gè)協(xié)議,而是支持互聯(lián)網(wǎng)運(yùn)行的一套協(xié)議的總稱,因此TCP/IP協(xié)議又被稱為TCP/IP協(xié)議簇。
TCP/IP是一種分層協(xié)議,它由多個(gè)交互的模塊構(gòu)成,每個(gè)模塊都提供了特定的功能,而這些模塊并不是必須相互依存的。也就是說(shuō),TCP/IP協(xié)議簇中的每一層中都包含一些相對(duì)獨(dú)立的協(xié)議,可以根據(jù)需要將這些協(xié)議進(jìn)行混合使用。從協(xié)議分層模型的角度來(lái)說(shuō),TCP/IP協(xié)議可以分為四層,它包括:網(wǎng)絡(luò)接口層、網(wǎng)絡(luò)層、傳輸層以及應(yīng)用層。其中,應(yīng)用層協(xié)議是TCP/IP協(xié)議簇與主機(jī)上應(yīng)用程序或進(jìn)程接口的地方,因此又被稱為處理層。在這一層上定義了對(duì)進(jìn)程或應(yīng)用程序的用戶接口,此時(shí)TCP/IP也因?yàn)閼?yīng)用層是直接為用戶提供服務(wù)的,所以應(yīng)用層上的協(xié)議大家也接觸的最多。比如訪問Web頁(yè)面所用到的HTTP協(xié)議,遠(yuǎn)程登錄所用到的Telnet協(xié)議,傳輸文件所用到的FTP協(xié)議以及發(fā)送郵件所用到的SMTP協(xié)議等等。在這里,TCP/IP協(xié)議與服務(wù)之間發(fā)生了重疊。每一個(gè)TCP/IP服務(wù)都有一個(gè)相應(yīng)的端口地址,用以識(shí)別特定的進(jìn)程和服務(wù)。
我們可以通過(guò)網(wǎng)絡(luò)編程的方式來(lái)實(shí)現(xiàn)這些網(wǎng)絡(luò)協(xié)議,目前較為流行的網(wǎng)絡(luò)編程模型是客戶端/服務(wù)器模式(C/S)。在通信的雙方中,作為客戶端的一方在需要獲得服務(wù)時(shí)向服務(wù)器端提出申請(qǐng),另一方作為服務(wù)器會(huì)處理客戶提出的請(qǐng)求并進(jìn)行相應(yīng)的響應(yīng)。服務(wù)器需要保證進(jìn)程始終運(yùn)行,同時(shí)它還需要監(jiān)聽網(wǎng)絡(luò)端口狀態(tài),一旦有客戶請(qǐng)求到來(lái)它就要及時(shí)的啟動(dòng)一個(gè)服務(wù)進(jìn)程來(lái)響應(yīng)該客戶,同時(shí)繼續(xù)監(jiān)聽端口狀態(tài)。
在這里,我們通過(guò)Telnet協(xié)議和FTP協(xié)議舉例說(shuō)明如何運(yùn)用C++語(yǔ)言進(jìn)行網(wǎng)絡(luò)編程從而實(shí)現(xiàn)相應(yīng)的網(wǎng)絡(luò)協(xié)議。當(dāng)用戶使用Telnet命令進(jìn)行遠(yuǎn)程登錄時(shí)首先得滿足以下條件:在本地主機(jī)上必須要安裝Telnet的客戶端程序,必須要知道遠(yuǎn)程主機(jī)或服務(wù)器的IP地址或者域名,還必須要知道登錄用的賬戶名與密碼。我們可以把Telnet遠(yuǎn)程登錄服務(wù)分解成以下四個(gè)工作過(guò)程:
(1)本地主機(jī)與遠(yuǎn)程主機(jī)之間連接的建立。該過(guò)程其實(shí)是建立了一個(gè)TCP的連接;
(2)將本地主機(jī)上用戶輸入標(biāo)識(shí)與口令及其用戶以后輸入的任何的命令或者字符用NVT的格式傳送到遠(yuǎn)程服務(wù)器或主機(jī)。該過(guò)程事實(shí)上是本地主機(jī)向遠(yuǎn)程主機(jī)發(fā)送一個(gè)IP數(shù)據(jù)報(bào);
(3)將遠(yuǎn)程主機(jī)發(fā)送的NVT格式的數(shù)據(jù)轉(zhuǎn)化為本地主機(jī)所能夠接受的格式,并把它發(fā)送給本地終端,其中包括了輸入命令的回顯以及執(zhí)行的結(jié)果;
(4)最后,本地主機(jī)和遠(yuǎn)程主機(jī)進(jìn)行連接的撤除,這是一個(gè)撤除TCP連接的過(guò)程。
數(shù)據(jù)信息是被用戶從鍵盤上輸入并通過(guò)系統(tǒng)傳到客戶機(jī)程序的,此程序?qū)⑵涮幚砗蠓祷亟o操作系統(tǒng),并由系統(tǒng)傳送給遠(yuǎn)地主機(jī),遠(yuǎn)地主機(jī)則把接收到的數(shù)據(jù)傳送到服務(wù)器程序,經(jīng)過(guò)服務(wù)器端程序處理后傳給操作系統(tǒng)中的偽終端入口點(diǎn),最后,遠(yuǎn)地的操作系統(tǒng)會(huì)將數(shù)據(jù)傳送給用戶正在使用的應(yīng)用程序,這就是一次完整輸入的過(guò)程;輸出則是從相同的通道從服務(wù)器端傳送到客戶端。
根據(jù)Telnet的工作過(guò)程,我們進(jìn)行C++編程,并且采用了Winsock網(wǎng)絡(luò)編程技術(shù),了Winsock是當(dāng)今最流行的網(wǎng)絡(luò)通信的接口,其接口具有開發(fā)、套接字規(guī)范和支持多種協(xié)議等特點(diǎn),這使得計(jì)算機(jī)之間的通信與文件的傳輸更加方便、安全。部分代碼如下所示:
CHostDialog host;
host.DoModal();
cHostName = host.m_HostName; //顯示選擇登錄的Telnet服務(wù)器對(duì)話框
BOOL bOK; //創(chuàng)建套接字,并連接服務(wù)器
cSock = new CClientSocket(this);
if(cSock != NULL)
{bOK = cSock->Create();
if(bOK == TRUE)
{//設(shè)置在該套接字上欲接收的消息
cSock->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE| FD_CONNECT | FD_OOB);
cSock->Connect(cHostName,23);
//建立連接
GetDocument()->SetTitle(cHostName);
Sleep(90); //等待}
else
{ASSERT(FALSE);
delete cSock;
cSock = NULL; }}
else
{ AfxMessageBox("Could not create new socket",MB_OK);}}
雖然Telnet給我們提供了很多方便,但其在安全方面存在的問題也是不容忽視的。盡管它要求用戶輸入登錄所用的賬戶名與密碼,但僅僅這些是不夠的,凡是連接在因特網(wǎng)上的主機(jī)都可以很容易的使用嗅探器來(lái)竊取賬戶名與密碼。正因?yàn)槿绱耍琓elnet的安全實(shí)現(xiàn)即Stelnet正變得越來(lái)越被重視,這些實(shí)現(xiàn)是使用的安全套接字層SSL(Secure Sockets Layer)的接口加密了Telnet客戶端與服務(wù)器端之間的數(shù)據(jù)流量,從而避免在網(wǎng)絡(luò)上泄漏了Telnet的安全標(biāo)識(shí)與口令。如果我們需要使用Telnet服務(wù),那么我們就有必要使用Telnet的安全實(shí)現(xiàn)。
另外,在使用FTP服務(wù)時(shí),F(xiàn)TP和主機(jī)之間建立了兩條連接。一條用來(lái)傳送數(shù)據(jù)(端口號(hào)20);一條用來(lái)傳送控制信息(端口號(hào)21)。FTP協(xié)議的這種把命令與控制信息分開的傳輸方式使得其效率更高。控制鏈路使用極其簡(jiǎn)單的通信規(guī)則,在其上面?zhèn)魉偷闹皇敲看我恍械拿罨蛘唔憫?yīng)信息;另一方面,數(shù)據(jù)的傳送則需要比控制信息的傳送更加復(fù)雜的規(guī)則,因?yàn)橐獋魉偷臄?shù)據(jù)的類型也是極其復(fù)雜的。而FTP數(shù)據(jù)連接的建立總共需要三個(gè)步驟:
客戶端使用一個(gè)臨時(shí)的端口發(fā)出被動(dòng)打開的命令,這必須是由客戶端來(lái)做的,因?yàn)槭强蛻舳税l(fā)出的文件傳送的命令的;
在客戶端則使用PORT命令把此臨時(shí)端口號(hào)傳送到服務(wù)器端;
服務(wù)器端在收到這個(gè)端口號(hào)后,使用20號(hào)端口與此臨時(shí)端口號(hào)立即發(fā)出主動(dòng)打開命令。
FTP的實(shí)現(xiàn)過(guò)程中的部分代碼如下所示:
m_Ctrlsok = socket(AF_INET,SOCK_STREAM,0);
//建立套接字失敗,則返回false
if (m_Ctrlsok == SOCKET_ERROR)
{ nRet = closesocket(m_Ctrlsok);
::WSACleanup();
return FALSE; }
//定義結(jié)構(gòu)體sockaddr_in,用于設(shè)置地址信息。
struct sockaddr_in sockAddr;
//將一個(gè)點(diǎn)間隔地址轉(zhuǎn)換成一個(gè)in_addr
sockAddr.sin_addr.S_un.S_addr=inet_addr(serverhost.GetBuffer(serverhost.GetLength()));
//設(shè)置協(xié)議簇,在socket編程中只能是AF_INET
sockAddr.sin_family=AF_INET;
//將主機(jī)的無(wú)符號(hào)短整型數(shù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序
sockAddr.sin_port=htons(serverport);
//連接服務(wù)器
if(0!=(connect(m_Ctrlsok,(sockaddr*)&sockAddr,sizeof(sockAddr))))
{ return FALSE;}
FTP協(xié)議在最初的設(shè)計(jì)時(shí),它的安全性并不是一個(gè)非常嚴(yán)重的問題。雖然FTP的連接是需要口令與密碼的,但是它的密碼是以明文形式發(fā)送的,并沒有進(jìn)行加密。攻擊者可以很容易的截取到這些信息。同時(shí),數(shù)據(jù)的傳送也是以明文的方式進(jìn)行的,這是極不安全的。要解決這些問題,就必須在FTP的應(yīng)用層與TCP的應(yīng)用層間加入安全套接層,即有SSL_FTP。
隨著網(wǎng)絡(luò)的普及面越來(lái)越廣,網(wǎng)絡(luò)應(yīng)用的日益深入,TCP/IP協(xié)議作為網(wǎng)絡(luò)通信的基礎(chǔ)協(xié)議將會(huì)被越來(lái)越多的人所了解、掌握。人們對(duì)TCP/IP應(yīng)用層協(xié)議的了解也將越來(lái)越深入。
[1]Behrouz A.Forouzan 著,王海等譯,《TCP/IP 協(xié)議族》[M],清華大學(xué)出版社,2011年1月。
[2]Laura A.Chappell Ed Tittel 著,張長(zhǎng)富等譯,《TCP/IP協(xié)議原理與應(yīng)用(第3版)》[M],清華大學(xué)出版社,2009年11月。
[3]W.Richard Stevens著,范建華等譯《TCP/IP詳解卷1:協(xié)議》[M],機(jī)械工業(yè)出版社,2000年4月。
[4]Gary R.Wright、 W.Richard Stevens著,陸雪瑩等譯,《TCP/IP詳解卷2:實(shí)現(xiàn)》[M],機(jī)械工業(yè)出版社,2004年1月。