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

C# Socket 連線池實作:長連線與短連線的折衷方案

     編輯:關於C語言

前言

高併發系統中,頻繁建立/關閉 Socket 連線(短連線)效能差;長期保持大量連線(長連線)佔用伺服器資源。連線池結合兩者優點:預先建立連線、閒置時重用、忙碌時等待、動態擴縮。本文提供完整實作範例。

連線模式對比

模式優點缺點適用場景
長連線無連線建立延遲、低延遲佔用伺服器連線數、需心跳維持即時通訊、遊戲、高頻交易
短連線釋放資源快、併發承載高三次交握開銷大、延遲高低頻請求、REST API、批次處理
連線池平衡延遲與資源、動態調整實作複雜、需管理狀態高併發、混合負載、企業級應用

核心設計:Socket 封裝類別


public class XiegouSocket
{
    public Socket Socket { get; set; }      // 底層 Socket
    public bool IsFree { get; set; }        // 閒置標記
    public int Index { get; set; }          // 池中索引
}

連線池建立完整程式碼


public XiegouSocket[] SocketPool { get; private set; }

public void CreateSocketPool(string ip = "127.0.0.1", int port = 2003, int poolSize = 200)
{
    IPAddress serverIp = IPAddress.Parse(ip);
    IPEndPoint endPoint = new IPEndPoint(serverIp, port);
    
    SocketPool = new XiegouSocket[poolSize];
    
    for (int i = 0; i < poolSize; i++)
    {
        var socketWrapper = new XiegouSocket
        {
            Index = i,
            IsFree = true,
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        };
        
        // 設定發送逾時 1 秒,避免阻塞
        socketWrapper.Socket.SetSocketOption(
            SocketOptionLevel.Socket, 
            SocketOptionName.SendTimeout, 
            1000);
        
        // 建立連線
        socketWrapper.Socket.Connect(endPoint);
        SocketPool[i] = socketWrapper;
    }
}

連線取得與歸還邏輯


// 取得可用連線(簡單版:輪詢尋找)
public XiegouSocket AcquireSocket()
{
    lock (SocketPool)
    {
        // 尋找閒置連線
        var freeSocket = SocketPool.FirstOrDefault(s => s.IsFree);
        if (freeSocket != null)
        {
            freeSocket.IsFree = false;
            return freeSocket;
        }
        
        // 可選:動態擴容或拋出例外/等待
        throw new InvalidOperationException("連線池耗盡,無可用連線");
    }
}

// 歸還連線
public void ReleaseSocket(XiegouSocket socket)
{
    lock (SocketPool)
    {
        if (socket != null && socket.Index >= 0 && socket.Index < SocketPool.Length)
        {
            socket.IsFree = true;
        }
    }
}

// 使用範例
public void SendData(byte[] data)
{
    var socket = AcquireSocket();
    try
    {
        socket.Socket.Send(data);
        // 接收回應...
    }
    finally
    {
        ReleaseSocket(socket);
    }
}

進階擴充建議

  • 非同步模式:使用 SocketAsyncEventArgs 或 await Socket.SendAsync() 避免阻塞執行緒
  • 健康檢查:定期發送心跳封包,移除失效連線並重建
  • 公平佇列:用 ConcurrentQueue<XiegouSocket> 管理閒置連線,避免輪詢
  • 動態縮放:監控使用率,超過 80% 擴容、低於 20% 縮容
  • 連線驗證:取得連線前檢查 Socket.Connected 與 Poll(0, SelectMode.SelectRead)
  • 統計監控:記錄取得/歸還耗時、等待次數、錯誤率,整合至 APM 系統

生產環境考量

總結

Socket 連線池是高併發網路程式的核心基礎設施。核心在於預先建立、狀態管理、閒置重用、動態調整。本文提供的基礎實作可直接用於中小型專案;大型系統建議採用成熟框架(如 System.Net.Http.HttpClient 內建連線池、gRPC、WCF、或第三方如 StackExchange.Redis 連線多工)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
風險緩解措施
連線洩漏(忘記 Release)使用 using 模式包裝 AcquireSocket() 回傳 IDisposable
死連線未偵測啟用 TCP Keep-Alive 或應用層心跳
執行緒飢餓採用非同步 I/O,避免同步阻塞執行緒池
連線風暴實作斷路器模式,失敗率過高時快速失敗