C#建立WebSocket服務端

慕色寒枝發表於2024-12-08

使用 C#建立 WebSocket 服務端的方法

1. 引入必要的名稱空間

using System.Text; // 用於傳送和接收資訊時處理文字
using System.Net;   // 用於處理網路連線
using System.Net.WebSockets; // 用於處理WebSocket連線

2. 例項化 HttpListener


const string HOST = "localhost";     // 監聽的主機名
const int PORT = 3030;              // 監聽的埠號

HttpListener listener = new HttpListener(); // 例項化HttpListener,這個需要作為一個全域性變數
listener.Prefixes.Add($"http://{HOST}:{PORT}/");  // 設定監聽的URL
listener.Start(); // 開始監聽

3. 處理客戶端的請求

async static Task ListenClientConnections()
{
    while (true)
    {
        // 等待客戶端的連線
        Console.WriteLine("等待客戶端連線");
        HttpListenerContext context = await listener.GetContextAsync();
        // 判斷此連線是否為WebSocket的請求
        if (context.Request.IsWebSocketRequest)
        {
            Console.WriteLine($"接收到客戶端連線");
            // 這時候,我們可以用WebSocket來接受客戶端的連線
            WebSocket webSocket = context.AcceptWebSocketAsync(null).Result.WebSocket;
            // 這時候我們可以根據需要來處理客戶端的訊息
            while (webSocket.State == WebSocketState.Open)
            {
                // 等待客戶端的訊息
                byte[] buffer = new byte[1024]; // 定義一個緩衝區大小為1KB
                ArraySegment<byte> segment = new ArraySegment<byte>(buffer);    // 定義一個陣列段

                CancellationToken cancellationToken = CancellationToken.None;   // 定義一個取消標記

                // 這時候這裡一直等待客戶端的訊息
                Console.WriteLine("等待客戶端訊息");
                WebSocketReceiveResult result = await webSocket.ReceiveAsync(segment, cancellationToken);

                // 文字型別的訊息
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    // 這裡可以對客戶端的訊息進行處理
                    string message = Encoding.UTF8.GetString(buffer, 0, result.Count);

                    // 給客戶端傳送訊息
                    string responseMessage = $"接收到客戶端的訊息: {message}";
                    Console.WriteLine(responseMessage);
                    byte[] responseBuffer = Encoding.UTF8.GetBytes(responseMessage);

                    await webSocket.SendAsync(
                        responseBuffer,     // 傳送的訊息,位元組陣列型別
                        WebSocketMessageType.Text,  // 訊息型別為文字
                        true,   // 最後一幀,如果為false,則表示後面還有資料
                        CancellationToken.None    // 取消標記
                    );
                }
            }
            Console.WriteLine("客戶端連線斷開");
        }
    }
}

4. 啟動服務端

ListenClientConnections().Wait(); // 啟動監聽客戶端連線的非同步方法

5. 客戶端連線

在這裡我們用 javascript 的 WebSocket 來模擬客戶端的連線,並向服務端傳送訊息。

let ws = new WebSocket("ws://localhost:3030/");
ws.onopen = function () {
  console.log("連線到服務端");

  // 傳送訊息
  ws.send("Hello World!!!");
};

ws.onclose = function () {
  console.log("與服務端連線斷開");
};

ws.onmessage = function ({ data }) {
  console.log("接收到服務端訊息");
  console.log(data);

  // ws.send("Hello World!!!");  // 猜猜會發生什麼?
  ws.close(); // 關閉連線
  console.log("關閉與服務端的連線");
};

ws.onerror = function () {
  console.log("WebSocket連線發生錯誤");
};

6. 執行結果

在服務端的控制檯中,我們可以看到:

等待客戶端連線
接收到客戶端連線
等待客戶端訊息
接收到客戶端的訊息: Hello World!!!
等待客戶端訊息
客戶端連線斷開
等待客戶端連線

在客戶端的控制檯中,我們可以看到:

連線到服務端
接收到服務端訊息
接收到客戶端的訊息: Hello World!!!
關閉與服務端的連線
與服務端連線斷開

到這裡,我們就完成了 C# 建立 WebSocket 服務端的方法。

完整程式碼

using System.Text; // 用於傳送和接收資訊時處理文字
using System.Net;   // 用於處理網路連線
using System.Net.WebSockets; // 用於處理WebSocket連線

namespace Test.Program
{
    static class Program
    {
        static HttpListener listener;
        static void Main(string[] args)
        {
            const string HOST = "localhost";     // 監聽的主機名
            const int PORT = 3030;              // 監聽的埠號

            listener = new HttpListener(); // 例項化HttpListener
            listener.Prefixes.Add($"http://{HOST}:{PORT}/");  // 設定監聽的URL
            listener.Start(); // 開始監聽
            ListenClientConnections()
                .Wait();
        }

        async static Task ListenClientConnections()
        {
            while (true)
            {
                // 等待客戶端的連線
                Console.WriteLine("等待客戶端連線");
                HttpListenerContext context = await listener.GetContextAsync();
                // 判斷此連線是否為WebSocket的請求
                if (context.Request.IsWebSocketRequest)
                {
                    Console.WriteLine($"接收到客戶端連線");
                    // 這時候,我們可以用WebSocket來接受客戶端的連線
                    WebSocket webSocket = context.AcceptWebSocketAsync(null).Result.WebSocket;
                    // 這時候我們可以根據需要來處理客戶端的訊息
                    while (webSocket.State == WebSocketState.Open)
                    {
                        // 等待客戶端的訊息
                        byte[] buffer = new byte[1024]; // 定義一個緩衝區大小為1KB
                        ArraySegment<byte> segment = new ArraySegment<byte>(buffer);    // 定義一個陣列段

                        CancellationToken cancellationToken = CancellationToken.None;   // 定義一個取消標記

                        // 這時候這裡一直等待客戶端的訊息
                        Console.WriteLine("等待客戶端訊息");
                        WebSocketReceiveResult result = await webSocket.ReceiveAsync(segment, cancellationToken);

                        // 文字型別的訊息
                        if (result.MessageType == WebSocketMessageType.Text)
                        {
                            // 這裡可以對客戶端的訊息進行處理
                            string message = Encoding.UTF8.GetString(buffer, 0, result.Count);

                            // 給客戶端傳送訊息
                            string responseMessage = $"接收到客戶端的訊息: {message}";
                            Console.WriteLine(responseMessage);
                            byte[] responseBuffer = Encoding.UTF8.GetBytes(responseMessage);

                            await webSocket.SendAsync(
                                responseBuffer,     // 傳送的訊息,位元組陣列型別
                                WebSocketMessageType.Text,  // 訊息型別為文字
                                true,   // 最後一幀,如果為false,則表示後面還有資料
                                CancellationToken.None    // 取消標記
                            );
                        }
                    }
                    Console.WriteLine("客戶端連線斷開");
                }
            }
        }
    }
}

客戶端

let ws = new WebSocket("ws://localhost:3030/");
ws.onopen = function () {
  console.log("連線到服務端");

  // 傳送訊息
  ws.send("Hello World!!!");
};

ws.onclose = function () {
  console.log("與服務端連線斷開");
};

ws.onmessage = function ({ data }) {
  console.log("接收到服務端訊息");
  console.log(data);

  // ws.send("Hello World!!!");  // 猜猜會發生什麼?
  ws.close(); // 關閉連線
  console.log("關閉與服務端的連線");
};

ws.onerror = function () {
  console.log("WebSocket連線發生錯誤");
};

相關文章