C# WebSocket 服务器未响应 pings

问题描述 投票:0回答:1

我已经成功编写了一个 csharp websocket 服务器并且客户端可以连接,但是客户端发送一条

ping
消息,但服务器没有响应
pong
,因此客户端断开连接。

经过进一步调查,结果发现我需要运行

ReadAsync
来捕获 ping 消息,但随后它处于等待状态,因此会阻止一切!

我很想访问底层套接字,这样我就可以执行

socket.available
来检查读取数据,但这是不可能的。

那么你应该如何用 C# 编写一个 websocket 服务器(不要说 SignalR!)来响应 ping 并确定客户端是否已断开!

using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;

class Program
{
    static async Task ClientHandler(HttpContext context)
    {
        using WebSocket socket = await context.WebSockets.AcceptWebSocketAsync();
        Console.WriteLine("Websocket client connected from {0}", socket.SubProtocol);

        var buffer = new byte[1024 * 4];
        WebSocketReceiveResult payload = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        string? message = Encoding.UTF8.GetString(buffer);
        Console.WriteLine("Received {0}", message);

        // workaround for replying to ping from client which requires ReceiveAsync to be active
        // Task.Run(async () =>
        // {
        //     await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        // });

        while (socket.State == WebSocketState.Open)
        {
            Console.WriteLine("Sending message...");
            byte[] msg = System.Text.Encoding.Default.GetBytes("Hello, World!");
            await socket.SendAsync(new ArraySegment<byte>(msg, 0, msg.Length), payload.MessageType, true, CancellationToken.None);

            Thread.Sleep(200);
        }

        await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "No more messages", CancellationToken.None);
        Console.WriteLine("Connection closed");
    }

    static void Main()
    {
        var app = WebApplication.CreateBuilder().Build();

        app.UseWebSockets();

        app.Use(async (context, next) =>
        {
            if (context.Request.Path == "/")
                if (context.WebSockets.IsWebSocketRequest)
                    await ClientHandler(context);
                else
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
            else
                await next(context);
        });

        app.Run("http://127.0.0.1:8001");
    }
}
c# websocket
1个回答
0
投票

检查此代码:

class Program
{
    static async Task ClientHandler(HttpContext context)
    {
        using WebSocket socket = await context.WebSockets.AcceptWebSocketAsync();
        Console.WriteLine("WebSocket client connected.");

        var buffer = new byte[1024 * 4];

        // Task to continuously receive messages
        var receiveTask = Task.Run(async () =>
        {
            while (socket.State == WebSocketState.Open)
            {
                var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                
                if (result.MessageType == WebSocketMessageType.Close)
                {
                    await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
                    Console.WriteLine("WebSocket client disconnected.");
                }
                else if (result.MessageType == WebSocketMessageType.Text)
                {
                    var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    Console.WriteLine("Received message: {0}", message);
                }
                else if (result.MessageType == WebSocketMessageType.Binary)
                {
                    Console.WriteLine("Received binary message of length: {0}", result.Count);
                }
                else if (result.MessageType == WebSocketMessageType.Close)
                {
                    Console.WriteLine("Received close message.");
                }
            }
        });

        // Task to continuously send messages
        var sendTask = Task.Run(async () =>
        {
            while (socket.State == WebSocketState.Open)
            {
                var msg = Encoding.UTF8.GetBytes("Hello, World!");
                await socket.SendAsync(new ArraySegment<byte>(msg, 0, msg.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                await Task.Delay(200);
            }
        });

        await Task.WhenAny(receiveTask, sendTask);

        Console.WriteLine("WebSocket connection closed.");
    }

    static void Main()
    {
        var builder = WebApplication.CreateBuilder();
        var app = builder.Build();

        app.UseWebSockets();

        app.Use(async (context, next) =>
        {
            if (context.Request.Path == "/ws")
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    await ClientHandler(context);
                }
                else
                {
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
                }
            }
            else
            {
                await next(context);
            }
        });

        app.Run("http://127.0.0.1:8001");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.