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

C# Socket TCP 程式設計完整架構與實作指南

     編輯:關於C#

前言

在 C# 中進行網路程式設計時,System.Net.Sockets.Socket 是最底層的操作類別。雖然封裝良好,但要建立高效、穩定的 TCP 伺服器,仍需妥善處理執行緒、非同步 I/O、連線管理等議題。本文提出一個經典的「主執行緒 + 監聽執行緒 + 工作執行緒」三層架構,並附上關鍵程式碼片段。

整體架構設計

  • WinForm 主執行緒:負責 UI 互動、啟動監聽、定期清理閒置連線。
  • Listener 執行緒:專責 Accept() 封包,接收新連線並建立 Connection 物件。
  • Connection 執行緒:每條連線獨立一條執行緒,處理收發訊息與心跳檢測。

關鍵程式碼實作

1. 啟動監聽執行緒

private void btn_startServer_Click(object sender, EventArgs e)
{
    Thread listenerThread = new Thread(new ThreadStart(WaitForConnect));
    listenerThread.Start();
}

private void WaitForConnect()
{
    SocketListener listener = new SocketListener(Convert.ToInt32(txt_port.Text));
    listener.StartListening();
}

若直接在 UI 執行緒呼叫 Accept() 會導致介面凍結,因此必須另闢執行緒。

2. Listener 迴圈與 Accept

IPEndPoint localEP = new IPEndPoint(_ipAddress, _port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

listener.Bind(localEP);
listener.Listen(20); // backlog = 20

while (true)
{
    Socket connection = listener.Accept(); // 同步阻塞,直到有新連線
    Logger.Log("Connect", connection.RemoteEndPoint.ToString());

    // 為每個連線建立獨立執行緒
    Connection conn = new Connection(connection);
    Thread t = new Thread(new ThreadStart(conn.WaitForSendData));
    t.Name = connection.RemoteEndPoint.ToString();
    t.Start();

    // 存入管理集合
    Connections.Add(conn, t);
}

3. Connection 訊息處理迴圈

public void WaitForSendData()
{
    while (true)
    {
        byte[] buffer = new byte[1024];
        int bytesRec = _connection.Receive(buffer); // 同步阻塞等待資料
        _lastConnectTime = DateTime.Now;

        if (bytesRec == 0) // 對方關閉連線
        {
            Logger.Log("Close Connection", _connection.RemoteEndPoint.ToString());
            break;
        }

        string data = Encoding.ASCII.GetString(buffer, 0, bytesRec);
        // TODO: 處理業務邏輯
    }
}

注意事項:

  1. Receive 同樣為阻塞呼叫,需在獨立執行緒執行。
  2. 回傳 0 表示對方正常關閉 (FIN 封包)。
  3. 大量資料需迴圈多次 Receive 直到讀完。
  4. 字節流需依協定編碼轉字串 (UTF-8、ASCII 等)。

4. 連線管理與閒置清理

// Listener 中的靜態集合
static public Hashtable Connections = new Hashtable(); // Connection -> Thread

// Connection 中記錄最後活動時間
private DateTime _lastConnectTime;

// WinForm 定時器定期掃描
foreach (DictionaryEntry entry in Connections)
{
    Connection c = (Connection)entry.Key;
    Thread t = (Thread)entry.Value;
    if ((DateTime.Now - c.LastConnectTime).TotalMinutes > TIMEOUT)
    {
        c.Close();
        t.Abort(); // 或優雅關閉
        Connections.Remove(c);
    }
}

效能與擴展建議

  • 大量連線時,執行緒池 或 非同步 Socket (BeginAccept/Receive) 可大幅降低資源消耗。
  • 考慮使用 SocketAsyncEventArgs (SAEA) 實現高效能 IOCP 模式。
  • 應用層協定建議採用「長度前綴」或「分隔符」解決黏包/拆包問題。

小結

本文示範的同步阻塞 + 每連線一執行緒模型,邏輯清晰、易於除錯,適合中小型專案或快速原型。面對高併發場景,建議遷移至非同步/IOCP 架構。

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