ZetCode

C# WebSocket

最后修改于 2023 年 7 月 5 日

在本文中,我们将展示如何在 C# 中使用 WebSocket。

WebSocket

WebSocket 是一种计算机通信协议,通过单个 TCP 连接提供全双工通信通道。WebSocket 用于高度交互式应用程序,例如游戏、聊天或股票市场。

我们创建一个支持 WebSocket 的 ASP.NET 应用程序。我们创建两个客户端:一个 C# 控制台程序和一个带有 JS 代码的 HTML 页面。

C# ASP.NET WebSocket 服务器

以下是一个简单的 WebSocket 服务器应用程序。

Program.cs
using System.Net;
using System.Net.WebSockets;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWebSockets();
app.Map("/ws", async context =>
{
    if (context.WebSockets.IsWebSocketRequest)
    {
        using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        var rand = new Random();

        while (true)
        {
            var now = DateTime.Now;
            byte[] data = Encoding.ASCII.GetBytes($"{now}");
            await webSocket.SendAsync(data, WebSocketMessageType.Text, 
                true, CancellationToken.None);
            await Task.Delay(1000);

            long r = rand.NextInt64(0, 10);

            if (r == 7)
            {
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,
                    "random closing", CancellationToken.None);

                return;
            }
        }
    }
    else
    {
        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
    }
});

app.Run("https://:5050");

该应用程序将当前日期时间发送到客户端。当随机数生成器选择值 7 时,我们将关闭连接。

using System.Net.WebSockets;

WebSocket 支持位于 System.Net.WebSockets 命名空间中。

app.UseWebSockets();

我们使用 UseWebSockets 启用 WebSocket 中间件。

app.Map("/ws", async context =>
{

我们将通信映射到 /ws 端点。

if (context.WebSockets.IsWebSocketRequest)
{

我们检查请求是否为 WebSocket 建立请求。

using var webSocket = await context.WebSockets.AcceptWebSocketAsync();

我们使用 AcceptWebSocketAsync 将请求转换为 WebSocket 连接。

var now = DateTime.Now;
byte[] data = Encoding.ASCII.GetBytes($"{now}");
await webSocket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);

我们使用 SendAsync 将数据发送到客户端。数据是当前日期时间。

long r = rand.NextInt64(0, 10);

if (r == 7)
{
    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,
        "random closing", CancellationToken.None);

    return;
}

我们使用 CloseAsync 随机关闭连接。

$ dotnet watch

我们使用 dotnet watch 启动服务器。

C# WebSocket 客户端

在下一个示例中,我们创建一个 C# 控制台程序,该程序建立与服务器的 WebSocket 连接。

Program.cs
using System.Net.WebSockets;
using System.Text;

Console.Title = "Client";

using var ws = new ClientWebSocket();

await ws.ConnectAsync(new Uri("ws://:5050/ws"), CancellationToken.None);
byte[] buf = new byte[1056];

while (ws.State == WebSocketState.Open)
{
    var result = await ws.ReceiveAsync(buf, CancellationToken.None);

    if (result.MessageType == WebSocketMessageType.Close)
    {
        await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None);
        Console.WriteLine(result.CloseStatusDescription);
    }
    else
    {
        Console.WriteLine(Encoding.ASCII.GetString(buf, 0, result.Count));
    }
}

我们从控制台应用程序建立与服务器的 WebSocket 连接。

using var ws = new ClientWebSocket();

ClientWebSocket 用于在 C# 应用程序中创建 WebSocket 客户端。

await ws.ConnectAsync(new Uri("ws://:5050/ws"), CancellationToken.None);

我们使用 ConnectAsync 异步连接到 ws://:5050/ws 端点。

byte[] buf = new byte[1056];

这是我们读取响应的缓冲区。

var result = await ws.ReceiveAsync(buf, CancellationToken.None);

我们使用 ReceiveAsync 读取响应。

if (result.MessageType == WebSocketMessageType.Close)
{
    await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None);
    Console.WriteLine(result.CloseStatusDescription);
}
else
{
    Console.WriteLine(Encoding.ASCII.GetString(buf, 0, result.Count));
}

如果消息类型为 WebSocketMessageType.Close,我们使用 CloseAsync 从客户端关闭连接,并打印关闭描述。否则,我们打印接收到的数据。

$ dotnet run
10/28/2022 2:57:48 PM
10/28/2022 2:57:49 PM
10/28/2022 2:57:50 PM
10/28/2022 2:57:51 PM
10/28/2022 2:57:52 PM
10/28/2022 2:57:53 PM
10/28/2022 2:57:54 PM
10/28/2022 2:57:55 PM
random closing

JS WebSocket 客户端

在下一个示例中,我们创建一个 JS 客户端,该客户端创建 WebSocket 连接。

index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script type="text/javascript">
        function connect() {

            let o = document.getElementById("output");
            var ws = new WebSocket("ws://:5050/ws");

            ws.onmessage = e => {
                o.innerText = e.data;
            };

            ws.onclose = e => {

                o.innerText = e.reason;
            };
        };


    </script>
</head>

<body>

    <div id="output">
    </div>

    <p>
        <a href="#" onclick="connect()">Start</a></div>
    </p>

</body>
</html>

在 JS 中,我们使用 WebSocket 类和 onmessageonclose 处理程序。

来源

WebSocket 类 - 语言参考

在本文中,我们已经学习了如何在 C# 中使用 WebSocket。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 C# 教程