簡體   English   中英

連接了多個客戶端的異步套接字服務器

[英]Async socket server with multiple clients connected

我想用C#編寫一個異步套接字服務器和客戶端。 服務器必須管理許多客戶端連接,並使其保持活動狀態。 我嘗試從此站點使用MSDN服務器代碼,但是它無法同時處理多個客戶端,並且在發送確認消息后關閉連接。 您能告訴我如何更改該示例代碼以管理同時向多個客戶端發送消息(例如,將客戶端連接置於某個數組或列表中)並使連接保持活動狀態嗎?

請注意,編寫異步服務器要比重寫MSDN示例花費更多的工作(我目前正在編寫處理4-5000個同時連接的異步服務器,這不是一件容易的事!)。

話雖如此,該樣本似乎完全能夠處理多個客戶。 但是,只要您不管理連接,就無法向客戶端發送任何消息,也無法以正常的方式關閉服務器(在關閉之前斷開所有客戶端的連接)。

如果只需要向所有客戶端廣播消息,則可以輕松列出所有連接的套接字。 即在AcceptCallback中,您應該將處理程序保存在列表中。 為了保持連接打開,請刪除SendCallback中的handler.Shutdown()和handler.Close()。 像這樣:

private List<Socket> _clients = new List<Socket>();

public static void AcceptCallback(IAsyncResult ar) {
    // Signal the main thread to continue.
    allDone.Set();

    // Get the socket that handles the client request.
    Socket listener = (Socket) ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReadCallback), state);

    _clients.Add(handler); // Maintain connected clients
}

public void BroadcastMessage(string message)
{
    // Send the message to all clients
    var bytes = Encoding.ASCII.GetBytes(message);
    foreach(var c in _clients)
    {
        c.BeginSend(bytes, 0, bytes.Length, SocketFlags.Broadcast, OnMessageBroadcast, c);
    }
}

private void OnMessageBroadcast(IAsyncResult res)
{
    Socket client = (Socket)res.AsyncState;
    client.EndSend(res);
}

如果您不熟悉服務器和套接字連接,則大致是事件流:

  1. 服務器創建一個偵聽器,該偵聽器將處理傳入的連接並提供回調

  2. 在偵聽器上調用BeginAccept以指示服務器已准備好處理連接

  3. 當客戶端連接時,偵聽套接字會回調:

    3a。 在偵聽器套接字上調用EndAccept提供了另一個套接字,在此發生實際的通信。

    3b。 要開始通信,請在通信套接字上調用BeginReceive,並提供一個回調,該回調將接收來自客戶端的消息

    3c。 再次調用BeginAccept表示您准備好接收新連接

  4. 收到消息后,通信套接字將回叫:

    4a。 調用EndReceive以讀取字節。 如果字節數為0,則另一端正在斷開連接

    4b。 處理消息並調用BeginReceive以接收下一條消息

  5. 當您要關閉連接時,發送Shutdown(Send),然后等待另一端通過關閉響應(在BeginReceive回調中將其顯示為0字節),然后關閉連接。

這只是一個粗略的概述,但是還有很多很多事情要做。 特別是異常處理可能非常棘手!

為了使整個內容更具可讀性,我首先將客戶端和服務器部分划分為單獨的類-否則所有的send和read方法很快就會變得難以區分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM