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

C# Socket 通訊與多執行緒總結(七):伺服端實作、Socket 類型與執行緒模型

     編輯:關於C語言

Socket 類型詳細對照

常數協定可靠性資料單位典型應用
SOCK_STREAMTCP可靠、有序、無重複位元組流Web、郵件、檔案傳輸
SOCK_DGRAMUDP不可靠、可能亂序/重複資料報DNS、串流、即時通訊
SOCK_RAWIP/ICMP原始封包IP 封包ping、路由追蹤

同步 TCP 伺服端完整實作


using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

public partial class ServerForm : Form {
    private Thread _listenThread;
    private Socket _serverSocket;

    protected override void Dispose(bool disposing) {
        try {
            _serverSocket?.Close();
            _listenThread?.Abort();
        } catch { }
        base.Dispose(disposing);
    }

    private static IPAddress GetLocalIP() {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        return host.AddressList.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
    }

    private void ListenLoop() {
        var ep = new IPEndPoint(GetLocalIP(), 8000);
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Bind(ep);
        _serverSocket.Listen(5);

        byte[] buffer = new byte[1024];
        while (true) {
            try {
                var client = _serverSocket.Accept(); // 阻塞等待連線
                int recv = client.Receive(buffer);
                string msg = $"{DateTime.Now:T}: {client.RemoteEndPoint} -> {Encoding.UTF8.GetString(buffer, 0, recv)}";
                Invoke(() => lstMessages.Items.Add(msg)); // 跨執行緒更新 UI
                client.Close();
            } catch (SocketException ex) {
                Invoke(() => lblStatus.Text = ex.Message);
            }
        }
    }

    private void btnStart_Click(object sender, EventArgs e) {
        try {
            _listenThread = new Thread(ListenLoop) { IsBackground = true };
            _listenThread.Start();
            lblStatus.Text = "Listening...";
        } catch (Exception ex) {
            MessageBox.Show(ex.Message);
        }
    }
}

關鍵架構決策

決策點同步阻塞模式非同步/IOCP 模式
併發能力單一執行緒串行處理單執行緒處理萬級連線
程式複雜度低高(APM/EAP/TAP)
適用場景內部工具、低負載、教學高併發伺服器、即時系統
資源佔用每連線一執行緒(若多執行緒版)少量執行緒池

多執行緒版伺服端(每連線一執行緒)


private void ListenLoop() {
    // ... Bind/Listen 同上 ...
    while (true) {
        var client = _serverSocket.Accept();
        ThreadPool.QueueUserWorkItem(HandleClient, client);
    }
}

private void HandleClient(object state) {
    var client = (Socket)state;
    try {
        byte[] buffer = new byte[1024];
        int recv = client.Receive(buffer);
        string msg = $"{DateTime.Now:T}: {client.RemoteEndPoint} -> {Encoding.UTF8.GetString(buffer, 0, recv)}";
        Invoke(() => lstMessages.Items.Add(msg));
    } catch (Exception ex) {
        Invoke(() => lstMessages.Items.Add($"Error: {ex.Message}"));
    } finally {
        client.Close();
    }
}

UI 執行緒安全:Invoke/BeginInvoke

  • WinForms 控制項只能在建立它們的執行緒存取
  • Control.Invoke(delegate):同步封送至 UI 執行緒
  • Control.BeginInvoke(delegate):非同步佇列,不阻塞工作執行緒
  • .NET Core / .NET 5+ 建議用 SynchronizationContext 或 Dispatcher

資源清理檢查清單

  1. Socket.Close() / Dispose() 釋放非託管控制代碼
  2. Thread.Abort() 停止監聽迴圈(或用 CancellationToken 優雅退出)
  3. Form.Dispose 中集中清理
  4. 設定 IsBackground = true 避免阻塞進程退出

效能調優提示

  • 接收緩衝區大小:Socket.ReceiveBufferSize(預設 8KB,高吞吐可調大)
  • Nagle 演算法:Socket.NoDelay = true 關閉,減少小封包延遲
  • 非同步 I/O:SocketAsyncEventArgs / ValueTask 避免分配
  • 連線池/物件池:重用 SocketAsyncEventArgs、緩衝區
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved