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

.NET 非同步 Socket 程式設計:從 BeginAccept 到 P2P 實作

     編輯:關於C#

為什麼需要非同步 Socket?

傳統阻塞式 Accept() 會凍結主執行緒,導致 UI 無回應。.NET Socket 類別內建非同步模式(APM),透過 BeginAccept/EndAccept、BeginReceive/EndReceive 等配對方法,搭配回呼函式,即可在不阻塞主執行緒的情況下處理高併發連線。

核心模式:事件驅動的回呼鏈

  1. 伺服端監聽:listener.BeginAccept(OnConnectRequest, listener)
  2. 連線建立:OnConnectRequest 中呼叫 listener.EndAccept() 取得 client socket,並立即 listener.BeginAccept(...) 繼續監聽下一個連線
  3. 資料接收:client.BeginReceive(OnReceivedData, client)
  4. 資料處理:OnReceivedData 中 EndReceive() 解析封包,處理完畢後再次 BeginReceive() 形成循環

關鍵代碼片段

伺服端啟動與接受連線

const int nPortListen = 399;
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(aryLocalAddr[0], nPortListen));
listener.Listen(10);
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);

public void OnConnectRequest(IAsyncResult ar) {
    Socket listener = (Socket)ar.AsyncState;
    Socket client = listener.EndAccept(ar);
    Console.WriteLine("Client {0} joined", client.RemoteEndPoint);
    // 送出歡迎訊息
    byte[] data = Encoding.ASCII.GetBytes("Welcome " + DateTime.Now + "\r\n");
    client.Send(data, data.Length, 0);
    // 繼續監聽下一個連線
    listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
}

客戶端非同步連線與接收

public void Connect(string serverAdd, int port) {
    clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    clientSock.Blocking = false;
    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(serverAdd), port);
    clientSock.BeginConnect(ep, new AsyncCallback(OnConnect), clientSock);
}

public void OnConnect(IAsyncResult ar) {
    Socket sock = (Socket)ar.AsyncState;
    if (sock.Connected) {
        sock.BeginReceive(msgBuff, 0, msgBuff.Length, SocketFlags.None,
            new AsyncCallback(OnReceivedData), sock);
    }
}

public void OnReceivedData(IAsyncResult ar) {
    Socket sock = (Socket)ar.AsyncState;
    try {
        int nBytes = sock.EndReceive(ar);
        if (nBytes > 0) {
            string msg = Encoding.ASCII.GetString(msgBuff, 0, nBytes);
            ParseMessage(sock, msg);
            SetupReceiveCallback(sock); // 重新掛接接收
        } else {
            sock.Shutdown(SocketShutdown.Both); sock.Close();
        }
    } catch { /* 錯誤處理 */ }
}

流程圖解

非同步 Socket 事件流程

非同步 Socket 事件觸發流程:BeginAccept → OnConnectRequest → BeginReceive → OnReceivedData → 再次 BeginReceive

P2P 擴充應用

範例實作一個簡易 P2P 節點:每個節點同時具備伺服端(start 400)與客戶端(connect ip port)功能,支援 get x y/set x y val 操作共享二維陣列。完整代碼可參考附件。

總結

.NET 非同步 Socket 透過 APM 模式將複雜的多執行緒同步問題轉化為事件回呼,大幅降低開發難度。掌握「啟動非同步操作 → 回呼中結束操作 → 立即發起下一個非同步操作」的循環模式,即可構建高效能網路服務。

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