首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作 HTTP Web Proxy 伺服器:從原理到多執行緒完整範例

     編輯:關於C語言

前言

Web Proxy(Web 代理伺服器)是網路應用中經典的「中介者」模式實作。本文將系統性說明:代理伺服器的優勢與風險、分層代理類型(應用層/傳輸層/SOCKS)、HTTP 代理的運作流程,並完整實作一個基於 TcpListener + Socket + 多執行緒的 C# HTTP Proxy,支援瀏覽器設定代理後直接瀏覽網頁。

一、為什麼需要 Web Proxy?

優勢說明
IP 位址共享區域網路內多台主機共用極少對外公網 IP
存取控制可過濾特定 IP/網域,充當防火牆角色
匿名性目標伺服器只看見 Proxy IP,隱藏客戶端真實身分
快取加速熱門資源暫存於 Proxy 硬碟,重複請求直接回應

風險提醒:所有流量經由 Proxy,若 Proxy 被惡意竊聽或頻寬不足,將導致資安外洩或速度下降。

二、代理類型與 HTTP Proxy 定位

  • 應用層代理:理解 HTTP/FTP 等協定,功能最豐富但需針對每種協定開發。本文實作即屬此類。
  • 傳輸層代理:僅轉發 TCP/UDP 封包,彈性較高但無法解析應用層語意。
  • SOCKS 代理:V4/V5 標準,支援驗證與 UDP,最通用但需客戶端修改 IP 堆疊。

三、HTTP Proxy 運作四步驟

  1. 接收並解析:讀取客戶端 HTTP Request,解析目標 Host、Port、Path。
  2. 建立上游連線:對目標 Web Server 建立新 Socket 連線(預設 Port 80)。
  3. 轉發請求:將原始 Request 完整傳送給上游。
  4. 接收回應並回傳:讀取上游 Response,原封不動轉發給客戶端。

關鍵點:每個客戶端請求獨立處理,故採用「一請求一執行緒」模型,每執行緒持有兩個 Socket(clientSocket 與 serverSocket)。

四、核心程式碼架構

1. Proxy 類別(處理單一請求)

public class Proxy
{
    private Socket _clientSocket;
    private byte[] _buffer = new byte[4096];
    private Encoding _ascii = Encoding.ASCII;

    public Proxy(Socket clientSocket) => _clientSocket = clientSocket;

    public void Run()
    {
        // 1. 讀取客戶端請求
        string request = ReadRequest();
        if (string.IsNullOrEmpty(request)) return;

        // 2. 解析目標 URL (簡易解析 GET https://host/path)
        string url = ParseUrl(request);
        if (string.IsNullOrEmpty(url)) return;

        // 3. 連線目標伺服器
        using var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        var hostEntry = Dns.GetHostEntry(url);
        var ipEndPoint = new IPEndPoint(hostEntry.AddressList[0], 80);
        serverSocket.Connect(ipEndPoint);

        // 4. 轉發請求
        byte[] reqBytes = _ascii.GetBytes(request);
        serverSocket.Send(reqBytes);

        // 5. 接收回應並轉發給客戶端
        RelayResponse(serverSocket);
    }

    private string ReadRequest() { /* 讀取直到雙 CRLF 或 Content-Length */ }
    private string ParseUrl(string request) { /* 簡易字串解析 */ }
    private void RelayResponse(Socket server) { /* 迴圈 Receive/Send */ }
}

2. 主程式(監聽與分派)

const int PORT = 8000;
var listener = new TcpListener(IPAddress.Any, PORT);
listener.Start();
Console.WriteLine($"Proxy listening on {PORT}...");

while (true)
{
    Socket clientSocket = listener.AcceptSocket();
    var proxy = new Proxy(clientSocket);
    Thread thread = new Thread(proxy.Run) { IsBackground = true };
    thread.Start();
}

五、關鍵技術細節與坑點

1. HTTP Request 解析

範例使用簡易 IndexOf 切割第一行 GET https://host/path HTTP/1.1。實務上需完整解析:

  • 支援 CONNECT 方法(HTTPS 隧道)
  • 處理 Host 標頭(HTTP/1.1 必備)
  • 處理 Chunked Transfer-Encoding、Content-Length、Gzip 等
  • 保持 Connection: keep-alive 連線重用

2. 非同步 I/O 與擴展性

範例使用同步 Send/Receive + 執行緒池,適合低併發。高併發建議改用:

  • SocketAsyncEventArgs 或 await Socket.ReceiveAsync
  • Pipe / Stream 雙向複製(CopyToAsync)
  • 連線池管理上游連線

3. HTTPS 支援(CONNECT 隧道)


// 客戶端發送:CONNECT www.example.com:443 HTTP/1.1
// Proxy 回應:HTTP/1.1 200 Connection Established
// 之後雙向透傳 TLS 封包,Proxy 不解密內容

完整 Proxy 必須實作 CONNECT,否則無法代理 HTTPS 流量。

4. 瀏覽器設定驗證

IE/Edge/Chrome 系統代理設定:

  1. Internet 選項 → 連線 → 區域網路設定
  2. 勾選「為 LAN 使用 Proxy 伺服器」
  3. 位址:Proxy 機器 IP,連接埠:8000

現代瀏覽器也可用擴充套件(SwitchyOmega、Proxy Switchy)切換。

六、現代化重構方向

  1. 使用 HttpClient + HttpRequestMessage 替代手工 Socket,自動處理協定細節。
  2. 引入 Titanium Web Proxy 等成熟庫,支援 HTTPS 解密、修改請求/回應、WebSocket、認證等。
  3. ASP.NET Core Middleware 實作反向代理(MapReverseProxy / YARP)。
  4. 加入存取日誌、速率限制、IP 白名單、快取策略(IMemoryCache/Redis)。

七、總結

這個範例雖然簡單,卻完整展示了 HTTP Proxy 的核心架構:監聽 → 分派執行緒 → 解析請求 → 建立上游連線 → 雙向轉發。理解這個流程,是深入網路程式設計、開發爬蟲中介、API Gateway、安全掃描器等進階應用的基石。現代開發建議站在巨人肩膀上(YARP、Titanium Web Proxy),專注於業務邏輯而非重造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved