實驗內(nèi)容
1. 設(shè)計并實現(xiàn)一個基本HTTP代理服務(wù)器。要求在指定端口接收來自客戶的HTTP請求并且根據(jù)其中的URL地址訪問該地址所指向的HTTP服務(wù)器(原服務(wù)器),接收HTTP服務(wù)器的響應(yīng)報文,并將響應(yīng)報文轉(zhuǎn)發(fā)給對應(yīng)的客戶進行瀏覽。
2. 設(shè)計并實現(xiàn)一個支持Cache功能的HTTP代理服務(wù)器。要求能緩存原服務(wù)器響應(yīng)的對象,并能夠通過修改請求報文(添加if-modified-since頭行),向原服務(wù)器確認緩存對象是否是最新版本。
3. 擴展HTTP代理服務(wù)器,支持如下功能:
- 網(wǎng)站過濾:允許/不允許訪問某些網(wǎng)站;
- 用戶過濾:支持/不支持某些用戶訪問外部網(wǎng)站;
- 網(wǎng)站引導(dǎo):將用戶對某個網(wǎng)站的訪問引導(dǎo)至一個模擬網(wǎng)站(釣魚)。
一、實驗總體思路
首先了解一下客戶端和服務(wù)器端的基本任務(wù):
客戶端(Client) | 服務(wù)器端(Server) |
---|---|
|
|
本實驗實現(xiàn)的即是一個HTTP代理服務(wù)器,接收并發(fā)送來自客戶的HTTP請求,同時轉(zhuǎn)發(fā)來自HTTP服務(wù)器的響應(yīng)報文到客戶端。在此過程中,既充當(dāng)客戶端,又充當(dāng)服務(wù)器端的角色。
二、實驗基礎(chǔ)代理部分
1.主函數(shù)
總體上使用InitSocket()函數(shù)初始化套接字socket,利用while(true)循環(huán)與listen函數(shù)實現(xiàn)對指定端口的持續(xù)監(jiān)聽;使用accept函數(shù)接收請求,同時創(chuàng)建子線程進行報文的轉(zhuǎn)發(fā)響應(yīng);處理完成后,等待200ms關(guān)閉該線程,并清理緩存;重復(fù)循環(huán)處理下一個請求
2. InitSocket()函數(shù)初始化套接字
此函數(shù)主要分為兩步:加載套接字庫和初始化套接字。
i). 加載套接字庫。此步驟加載Socket庫,并檢查winsock.dll的加載是否成功以及版本是否匹配。
ii). 初始化套接字。利用socket(AF_INET,SOCK_STREAM)方法創(chuàng)建套接字,第一個參數(shù)代表協(xié)議族,AF_INET表示是IPV4地址簇;第二個參數(shù)代表套接字類型,SOCK_STREAM表示是面向TCP連接的流式套接字;有時后面還會有第三個參數(shù),代表協(xié)議號,默認設(shè)置為0;而后使用bind()方法將套接字與本機地址及響應(yīng)端口綁定,并設(shè)置為監(jiān)聽狀態(tài)。
3. ProxyThread()線程處理函數(shù)
在線程函數(shù)中,首先需要使用ZeroMemory()方法初始化內(nèi)存,再使用recv()函數(shù)接收來自客戶端的HTTP請求,消息內(nèi)容緩存在Buffer中,recvSize為實際收到的報文字節(jié)數(shù),而后使用ParseHttpHead函數(shù)對HTTP報文首部進行解析。
之后調(diào)用ConnectToServer函數(shù),根據(jù)發(fā)送端套接字的協(xié)議族和端口號還有套接字類型,以及目的主機的IP地址和端口號進行建立和服務(wù)器之間的連接。連接成功后,調(diào)用send()將客戶端發(fā)送的HTTP請求報文轉(zhuǎn)發(fā)給目標服務(wù)器。
接下來調(diào)用recv()函數(shù)等待目標服務(wù)器返回數(shù)據(jù),可以理解為網(wǎng)頁內(nèi)容, 接受之后將返回的數(shù)據(jù)直接轉(zhuǎn)發(fā)給客戶端,結(jié)束本次線程處理。
最后是異常處理,如果在過程中有異常均跳轉(zhuǎn)到error,結(jié)束線程運行。
4. ParseHttpHead()HTTP頭部解析函數(shù)
根據(jù)下圖HTTP請求報文頭部結(jié)構(gòu),使用strtok_s()方法對報文信息進行分割提取,得到方法、URL、Host、Cookie等信息。
5. ConnectToServer ()函數(shù)連接服務(wù)器
與InitSocket()函數(shù)中創(chuàng)建套接字過程類似,根據(jù)發(fā)送端套接字的協(xié)議簇和端口號還有套接字類型,以及目的主機的IP地址和端口號進行建立連接,如果連接成功,放回TRUE。
三、Cache部分功能設(shè)計
當(dāng)訪問某網(wǎng)站時,首先通過URL對應(yīng)的文件名尋找本地對應(yīng)緩存文件,
1) 若無對應(yīng)文件,即為第一次訪問某網(wǎng)站,則代理服務(wù)器通過writeinCache()函數(shù)將該請求返回的響應(yīng)數(shù)據(jù)寫入緩存即相應(yīng)文件中
2) 若匹配到本地緩存文件,則獲取文件中的Date信息,利用MakeNewHTTP()函數(shù)構(gòu)造條件GET報文,即為報文在Host后插入If-Modified-Since頭部行。
再向服務(wù)器端發(fā)送請求,通過服務(wù)器返回的數(shù)據(jù)碼判斷是否為最新的數(shù)據(jù),若返回304,則內(nèi)容并未再次更新,直接使用readCache()方法讀取緩存中的內(nèi)容并轉(zhuǎn)發(fā)給客戶端;若返回200,則將此響應(yīng)報文直接發(fā)給客戶端,同時更新本地緩存。
由于上述writeinCache(),readCache(),MakeNewHTTP()均為簡單的文件讀寫、字符串插入等操作,此處不再給出截圖。
四、擴展功能設(shè)計
a) 網(wǎng)站過濾:允許/不允許訪問某些網(wǎng)站;
設(shè)置字符串?dāng)?shù)組存儲屏蔽網(wǎng)站地址,對請求的HTTP報文頭部進行解析,提取其
中的訪問地址URL,并與屏蔽網(wǎng)站地址進行匹配,若匹配成功,則代碼跳轉(zhuǎn)至error部分,打印相關(guān)提示信息,立即關(guān)閉套接字,斷開連接。
b) 用戶過濾:支持/不支持某些用戶訪問外部網(wǎng)站;
一種方法是直接更改套接字綁定的主機地址,綁定主機127.0.0.1即限制僅本機用戶可訪問服務(wù)器ProxyServerAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1")。
也可以在accept()監(jiān)聽套接字時獲取客戶端IP與禁止訪問IP進行字符串比較以實現(xiàn)用戶屏蔽。
c) 網(wǎng)站引導(dǎo):將用戶對某個網(wǎng)站的訪問引導(dǎo)至一個模擬網(wǎng)站
設(shè)置字符串?dāng)?shù)組存儲釣魚網(wǎng)站地址,設(shè)置引導(dǎo)目的網(wǎng)站地址,同樣解析匹配URL,若匹配成功,則更改HTTP頭部字段的訪問網(wǎng)址URL 與Host主機地址,實現(xiàn)網(wǎng)頁的釣魚跳轉(zhuǎn)。文章來源:http://www.zghlxwxcb.cn/news/detail-837036.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-837036.html
到了這里,關(guān)于哈工大計算機網(wǎng)絡(luò)實驗一——HTTP代理服務(wù)器的設(shè)計與實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!