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

C# 實現 HTTP 代理伺服器:Socket 非同步多線程架構完整實戰

     編輯:關於C語言

代理伺服器分類

本文實作 HTTP 應用層代理 (Web Proxy)。

HTTP 代理工作流程

  1. 客戶端瀏覽器設定代理 IP:Port,發送 HTTP 請求 (含完整 URL)
  2. 代理解析請求行取得目標 Host:Port
  3. 代理建立 Socket 連線目標 Web 伺服器 (預設 80 埠)
  4. 代理轉發原始請求給目標伺服器
  5. 代理接收回應 (含標頭 + 體)
  6. 代理轉發回應給客戶端

核心架構:每請求一線程

// 主線程:監聽 + 分派
TcpListener listener = new TcpListener(8000);
listener.Start();
while (true)
{
    Socket clientSocket = listener.AcceptSocket();
    var proxy = new ProxyHandler(clientSocket);
    Thread t = new Thread(proxy.ProcessRequest);
    t.Start(); // 或 ThreadPool.QueueUserWorkItem
}

ProxyHandler 核心實作

public class ProxyHandler
{
    private readonly Socket _clientSocket;
    private const int BufferSize = 4096;

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

    public void ProcessRequest()
    {
        try
        {
            // 1. 讀取客戶端請求
            byte[] reqBuffer = new byte[BufferSize];
            int bytesRead = _clientSocket.Receive(reqBuffer);
            if (bytesRead == 0) return;
            string request = Encoding.ASCII.GetString(reqBuffer, 0, bytesRead);

            // 2. 解析目標 Host (簡易解析 GET https://host/path HTTP/1.1)
            string host = ParseHost(request);
            if (string.IsNullOrEmpty(host)) return;

            // 3. 連線目標伺服器
            IPAddress[] addresses = Dns.GetHostAddresses(host);
            IPEndPoint remoteEP = new IPEndPoint(addresses[0], 80);
            using (Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                serverSocket.Connect(remoteEP);
                if (!serverSocket.Connected) return;

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

                // 5. 接收回應並轉發給客戶端 (串流式,避免大檔案記憶體壓力)
                byte[] respBuffer = new byte[BufferSize];
                int read;
                while ((read = serverSocket.Receive(respBuffer)) > 0)
                {
                    _clientSocket.Send(respBuffer, read, SocketFlags.None);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Proxy error: {ex.Message}");
        }
        finally
        {
            _clientSocket.Close();
        }
    }

    private string ParseRequest(string request)
    {
        // GET https://www.example.com/path HTTP/1.1
        // 取得 www.example.com
        int start = request.IndexOf("https://");
        if (start < 0) return null;
        start += 7;
        int end = request.IndexOf('/', start);
        if (end < 0) end = request.IndexOf(' ', start);
        if (end < 0) return null;
        return request.Substring(start, end - start);
    }
}

關鍵技術點

  • 雙 Socket 模型:Client Socket (瀏覽器↔代理) + Server Socket (代理↔目標站)
  • 串流式轉發:邊收邊送,避免大檔案佔用記憶體
  • 編碼處理:HTTP 標頭為 ASCII/ISO-8859-1,Body 視 Content-Type 而定
  • 連線復用:HTTP/1.1 Keep-Alive 需解析 Connection 標頭,維持雙向長連線 (進階)
  • HTTPS 支援:CONNECT 方法建立隧道,需 TLS 握手透傳 (本範例未實作)

客戶端設定驗證

  1. IE/Edge/Chrome:設定 → 網路 → 代理 → 位址 代理IP、埠 8000
  2. 瀏覽任意 HTTP 網站,觀察代理主控台輸出

生產級強化建議

  • 使用 SocketAsyncEventArgs / await SocketTaskExtensions 實現高併發非同步 I/O
  • 引入快取 (MemoryCache/Redis)、過濾規則、存取日誌、流量統計
  • 支援 HTTPS CONNECT 隧道、HTTP/2、WebSocket 升級
  • 身份驗證 (Basic/Digest/NTLM)、IP 白名單、頻率限制
  • 優雅關閉:停止接受新連線、等待進行中請求完成、釋放資源
  • 考慮成熟專案:Titanic、ProxyServer、Ocelot (API Gateway)

總結

本文展示了基於 TcpListener + Socket + 多線程的 HTTP 代理核心邏輯:解析請求 → 建立上游連線 → 雙向串流轉發。雖屬教學級實作,但涵蓋代理伺服器最本質的「橋樑」角色。現代高效能代理建議採用非同步 I/O (IOCP) + 管線化處理,並整合安全、可觀測性與協議擴展能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
層級類型特點
應用層HTTP/FTP/SMTP Proxy理解協議內容,可過濾/修改/快取,需各協議支援
傳輸層Port Mapping / TCP Proxy透明轉發 TCP 流,通用但無法檢視應用層語義
會話層SOCKS4/5標準化、支援認證、UDP 轉發、最靈活