Visual C#實現HTTP代理服務程式
1
網路代理程式的種類非常多,根據代理服務程式代理的協議不同,分成HTTP代理服務程式、FTP代理服務程式等,執行代理服務程式的伺服器也就稱為HTTP代理伺服器和FTP代理伺服器。在本節中介紹的Web代理服務程式代理的就是HTTP協議。
一.網路代理的型別及實現原理:
網路代理服務根據工作層次,一般可分為應用層代理、傳輸層代理和SOCKS代理。應用層代理是工作在TCP/IP參考模型的應用層之上,它支援對應用層協議(如HTTP,FTP)的代理。它提供的控制最多,但是不靈活,必須要有相應的協議支援。如果協議不支援代理(如SMTP和POP),那就只能在應用層以下代理,也即傳輸層代理。傳輸層代理直接與TCP層互動,更加靈活。要求代理伺服器具有部分真正伺服器的功能:監聽特定TCP或UDP埠,接收客戶端的請求同時向客戶端發出相應的響應。另一種代理需要改變客戶端的IP棧,即SOCKS代理。它是可用的最強大、最靈活的代理標準協議。SOCK V4允許代理伺服器內部的客戶端完全地連線到外部的伺服器,SOCK
網路代理就是一個連線客戶端(設定需要代理的計算機)和伺服器端(需要訪問資源的伺服器)的橋。要實現這種橋,網路代理就必須滿足下列條件,其實也是代理服務的執行的流程:
(1). 能夠接收並解析客戶端的請求。
(2). 建立到伺服器的新連線,並根據轉發客戶端的請求資訊。
(3). 接收伺服器反饋的資訊。
(4). 能夠發出或解釋伺服器的響應並將該響應傳回給客戶端。
圖01是網路代理服務的一個典型模型圖:
|
二.Visual C#實現Web代理服務程式
Web代理服務是代理服務中最常用的一種代理服務,按照代理服務的層次,它屬於應用層代理,是對TCP/IP參考模型中的應用層的HTTP協議的代理。
Web代理服務也是代理服務中的一種,所以它也要滿足代理服務的基本條件。在下面介紹的代理服務程式中,是按照下列的順序來實現其功能的。
(1). 代理伺服器程式偵聽埠,接收客戶端瀏覽器傳送來的Web請求資訊。
(2). 代理伺服器程式接收到客戶端Web請求資訊後,解析出Web伺服器的地址,並建立一個Socket例項,並以此例項連線Web伺服器上。
(3). 通過建立的Socket傳送客戶端的Web請求資料包到Web伺服器的80埠。
(4). 代理伺服器程式接收Web伺服器返回頁面資料。
(5). 代理伺服器程式把接收來的資料傳送到客戶端,實現Web代理。
由於客戶端的對一個地址的瀏覽,要傳送很多的Web請求資訊,為了更快、更準確的處理這些資訊,Web代理服務程式採用了多執行緒來處理每一個Web請求。細心的讀者可能會發現,處理每一個客戶端的Web請求資訊,代理伺服器軟體都要使用二個Socket,一個是用來接收/傳送客戶機的資訊,一個是和Web伺服器進行交流。為了區分這二個Socket,我們把他們都命名,和伺服器對話的Socket,稱為服務Socket;和客戶端機器對話的Scoket,稱為客戶Socket。
下面就開始Web代理服務程式的編寫工作。
這個示例主要包含三個部分內容:
·建立一個Web代理類。
·Web代理服務的類的例項化。
·如何通過這個Web代理類的例項實現Web代理服務。
下面就是第一部分的具體的實現步驟。
(一).建立一個Web代理類
以下是具體的操作步驟如下:
1. 首先啟動Visual Studio .Net,依次選擇"
2. 選擇選單【專案】|【新增類】,彈出【新增新項】對話方塊
3. 將【模板】設定【類】
4. 在【名稱】文字框中輸入【Proxy】,單擊【開啟】按鈕,具體如圖02所示。
圖02:Web代理專案中【新增新項】對話方塊
5. 在【解決方案資源管理器】視窗中,雙擊Proxy.cs檔案,進入Proxy.cs檔案的編輯介面。
6. 在Proxy.cs原始檔的開頭,新增下列程式碼,下列程式碼是匯入Proxy.cs中要使用到的名稱空間:
using System ; using System.Net ; using System.Net.Sockets ; using System.Text ; using System.IO ; |
2
7. 用下列建構函式替代預設的建構函式。下面的程式碼是在Proxy類中建立一個建構函式。 Proxy類只有一個建構函式,並且這個建構函式只有一個引數,這個引數是Socket物件,它主要用來和客戶端進行資料交換,是一個客戶Socket.。
public Proxy ( Socket socket ) { // // TODO: 在此處新增建構函式邏輯 // this.clientSocket = socket ; } |
8. 建立Proxy類中的Run方法,Run方法是Proxy類中唯一的方法。其功能是從客戶端接收HTTP請求,並傳送到Web伺服器,然後從Web伺服器接收反饋來的資料,並傳送到客戶端。為了實現這二個不同方面的資料傳送,Run方法中是通過二個Socket例項來實現的。在編寫Run方法的時候,要注意下面幾點:
(1). 由於HTTP是TCP/IP參考模型中的應用層協議,它建立於TCP協議之上,所以建立的Socket例項使用的協議型別應該為TCP協議。下面程式碼是建立可以傳送HTTP請求命令到Web伺服器和接收來自Web伺服器反饋來資訊的Socket例項:
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp); |
(2). 另外一個Socket是在代理服務程式偵聽埠號,接收掛起的連線請求時候得到的,以此Socket為引數,利用Proxy類中的建構函式,來建立一個Proxy例項的。此Socket實現從客戶端接收HTTP請求資訊,並傳送資料到客戶端。
Socket建立和使用是實現Web代理軟體的關鍵,具體實現方法是在建構函式程式碼後面,輸入下列程式碼,建立Proxy類的Run方法:
public void Run ( ) { string clientmessage = " " ; //存放來自客戶端的HTTP請求字串 string URL = " " ; //存放解析出地址請求資訊 int bytes = ReadMessage ( read , ref clientSocket , ref clientmessage ) ; if ( bytes == 0 ) { return ; } int index1 = clientmessage.IndexOf ( ' ' ) ; int index2 = clientmessage.IndexOf ( ' ' , index1 + 1 ) ; if ( ( index1 == -1 ) || ( index2 == -1 ) ) { throw new IOException ( ) ; } string part1 = clientmessage.Substring ( index1 + 1 , index2 - index1 ) ; int index3 = part1.IndexOf ( '/' , index1 + 8 ) ; int index4 = part1.IndexOf ( ' ' , index1 + 8 ) ; int index5 = index4 - index3 ; URL = part1.Substring ( index1 + 4 , ( part1.Length - index5 ) - 8 ) ; try { IPHostEntry IPHost = Dns.Resolve ( URL ) ; Console.WriteLine ( "遠端主機名: " + IPHost.HostName ) ; string [] aliases = IPHost.Aliases ; IPAddress[] address = IPHost.AddressList ; Console.WriteLine ( "Web伺服器IP地址:" + address[0] ) ; //解析出要訪問的伺服器地址 IPEndPoint ipEndpoint = new IPEndPoint ( address[0] , 80 ) ; Socket IPsocket = new Socket ( AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp ) ; //建立連線Web伺服器端的Socket物件 IPsocket.Connect ( ipEndpoint ) ; //Socket連Web接伺服器 if ( IPsocket.Connected ) Console.WriteLine ( "Socket 正確連線!" ) ; string GET = clientmessage ; Byte[] ByteGet = ASCII.GetBytes ( GET ) ; IPsocket.Send ( ByteGet , ByteGet.Length , 0 ) ; //代理訪問軟體對伺服器端傳送HTTP請求命令 Int32 rBytes = IPsocket.Receive ( RecvBytes , RecvBytes.Length , 0 ) ; //代理訪問軟體接收來自Web伺服器端的反饋資訊 Console.WriteLine ( "接收位元組數:" + rBytes.ToString ( ) ) ; String strRetPage = null ; strRetPage = strRetPage + ASCII.GetString ( RecvBytes , 0 , rBytes ) ; while ( rBytes > 0 ) { rBytes = IPsocket.Receive ( RecvBytes , RecvBytes.Length , 0 ) ; strRetPage = strRetPage + ASCII.GetString ( RecvBytes , 0 , rBytes ) ; } IPsocket.Shutdown ( SocketShutdown.Both ) ; IPsocket.Close ( ) ; SendMessage ( clientSocket , strRetPage ) ; //代理服務軟體往客戶端傳送接收到的資訊 } catch ( Exception exc2 ) { Console.WriteLine ( exc2.ToString ( ) ) ; } } //接收客戶端的HTTP請求資料 private int ReadMessage ( byte [ ] ByteArray , ref Socket s , ref String clientmessage ) { int bytes = s.Receive ( ByteArray , 1024 , 0 ) ; string messagefromclient = Encoding.ASCII.GetString ( ByteArray ) ; clientmessage = ( String )messagefromclient ; return bytes ; } //傳送從Web伺服器反饋的資料到客戶端 private void SendMessage ( Socket s , string message ) { Buffer = new Byte[message.Length + 1] ; int length = ASCII.GetBytes ( message , 0 , message.Length , Buffer , 0 ) ; Console.WriteLine ( "傳送位元組數:" + length.ToString ( ) ) ; s.Send ( Buffer , length , 0 ) ; } |
9. 在定義Proxy類程式碼區中加入下列程式碼,下列程式碼是定義Proxy類中的使用的一些變數,這些變數主要是在後面的定義Run方法中使用。
Socket clientSocket ; Byte[] read = new byte[1024] ; //定義一個空間,儲存來自客戶端請求資料包 Byte [] Buffer = null ; Encoding ASCII = Encoding.ASCII ; //設定編碼 Byte[] RecvBytes = new Byte[4096] ; //定義一個空間,儲存Web伺服器返回的資料 |
10. 至此,Proxy類的定義過程就完成了。把Proxy類例項化非常簡單,和以前用的其他完全一樣,具體語法如下:
public Proxy ( Socket socket ); |
引數:socket為一個Scoket例項
下面程式碼是建立一個Proxy例項:
Proxy proxy = new Proxy ( socket ) ; |
3
(二). 利用Proxy類,實現Web代理的具體示例:
下面是利用上面建立的Proxy類,實現Web代理程式的具體實現步驟,Proxy類被定義在名稱空間WebProxy中。
1. 在Visual Studio .Net的程式碼編輯器中開啟Class1.cs檔案,進入Class1.cs的程式碼編輯介面。
2. 在Class1.cs原始檔的開頭匯入下列名稱空間:
using System ; using System.Net ; using System.Net.Sockets ; using System.Text ; using System.IO ; using System.Threading ; using WebProxy ; //其中名稱空間WebProxy是Proxy類所處的位置,具體可以參閱Proxy.cs原始檔 //中名稱空間的定義。 |
3. 在Main函式中新增下列程式碼,下列程式碼是利用Proxy類,來實現Web代理程式。
const int port = 8000 ; //定義埠號 TcpListener tcplistener = new TcpListener ( port ) ; Console.WriteLine ( "偵聽埠號: " + port.ToString ( ) ) ; tcplistener.Start ( ) ; //偵聽埠號 while ( true ) { Socket socket = tcplistener.AcceptSocket ( ) ; //並獲取傳送和接收資料的Scoket例項 Proxy proxy = new Proxy ( socket ) ; //Proxy類例項化 Thread thread = new Thread ( new ThreadStart ( proxy.Run ) ) ; //建立執行緒 thread.Start ( ) ; //啟動執行緒 } |
儲存上面的所有步驟,這樣一個簡單Web代理程式就算是完成了。此Web代理程式偵聽的是8000埠號。
(三).測試Web程式碼程式:
Web代理程式要通過二臺計算機才能夠實現。其中的一臺計算機執行Web代理程式,充當Web代理伺服器。另外一臺計算機充當客戶機,通過Web代理伺服器來瀏覽網頁。在確定Web代理軟體執行後,下面是對客戶機進行必要的設定。
1. 開啟IE瀏覽器。
2. 選擇【工具】|【Internet選項】,彈出【Internet選項】對話方塊。在此對話方塊中選擇【連線】頁面,單擊其中的【區域網設定】按鈕。彈出【區域網(LAN)設定】對話方塊。選擇【為LAN使用代理伺服器(X),(這些設定不會應用於撥號和VPN連線)】多選框。並在其中的【地址】文字框中輸入代理伺服器的IP地址,由於測試的代理伺服器的IP地址為"10.138.198.213",所有也輸入此IP地址,在【埠】文字框中輸入"8000"。具體如圖03所示:
|
此時客戶端的設定就完成了,在確定IP地址為"10.138.198.213"的這臺計算機已經執行上面介紹的Web代理程式後。開啟客戶端的IE瀏覽器,並輸入要瀏覽的網址,就可以通過Web代理伺服器來瀏覽網頁了,圖04是Web代理服務程式在伺服器端執行時的介面。
|
四.總結:
至此一個簡單的Web代理服務軟體就算基本完成了,通過上面內容的介紹可見,雖然代理服務的實現原理相對簡單,但具體實現其實還是很繁瑣的。網路代理是一個內容豐富,實現複雜的論題,本節介紹的代理服務軟體,無論在實現的協議種類,還是實現的功能,都只能算很小的一部分。希望各位能夠通過本文的介紹,結合其他相關的知識,創造出功能更強大、安全性更高,使用更穩定的網路代理服務程式來。