Search code examples
c#asp.net-corewebsocketserverclient

How to use websockets in asp.net core


im trying to develop a game where i store a scoreboard in a text file which is stored on server (currently on localhost). I am using http get and post calls in order to communicate with the server and get and send the data that i want. Now i want to implement websockets in order to send a notification from the server to the c# client. The notification will just display on the console a message for the user, for example in mu case i want to display a message to the user each time a user is added to the scoreboard, each time the UpdateScoreBoard method is called. Based on tutorials i found online i have managed to build the following code, can anyone make it more clear for me how the i will build the websocket for the server and how i will initialize the websocket on the client? Thank you

Startup.cs (Server)

        public void Configure(IApplicationBuilder app, IHostEnvironment env)
        {
          //deleted code

            var webSocketOptions = new WebSocketOptions()
            {
                KeepAliveInterval = TimeSpan.FromSeconds(120),
                ReceiveBufferSize = 4 * 1024
            };


            app.UseWebSockets(webSocketOptions);
        
            app.Use(async (context, next) =>
            {
                if (context.Request.Path == "/ws")
                {
                    if (context.WebSockets.IsWebSocketRequest)
                    {
                        WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                        await Echo(context, webSocket);
                    }
                    else
                    {
                        context.Response.StatusCode = 400;
                    }
                }
                else
                {
                    await next();
                }

            });
        }

        private async Task Echo(HttpContext context, WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            while (!result.CloseStatus.HasValue)
            {
                await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);

                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            }
            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        }

HttpClass.cs (Client) - where i call the http post request

public async override Task<List<Scoreboard>> UpdateScoreBoards(string username, int attempts, int seconds, DateTime date)
            {
                HttpResponseMessage response = null;
                //Creating a new instance of object Scoreboard
                //deleted code

                var url = "http://localhost:5000/api/Scoreboard";

                var socket_url = new Uri("ws://localhost:5000"); 
                var exitEvent = new ManualResetEvent(false);
                using (var client = new WebsocketClient(socket_url))
                {
                    client.ReconnectTimeout = TimeSpan.FromSeconds(30);
                    client.ReconnectionHappened.Subscribe(info =>
                        Log.Information($"Reconnection happened, type: {info.Type}"));

                    client.MessageReceived.Subscribe(msg => Log.Information($"Message received: {msg}"));
                    await client.Start();

                    await Task.Run(() => client.Send("test"));

                    exitEvent.WaitOne();
                }

// deleted code
            }

Solution

  • can anyone make it more clear for me how the i will build the websocket for the server and how i will initialize the websocket on the client?

    As the example that you referenced demonstrated, making use of WebSocket in ASP.NET Core, we can add the WebSockets middleware in the Configure method, then add/configure request delegate to check and handle incoming WebSocket requests.

    And after transitioned a request to a WebSocket connection with AcceptWebSocketAsync() method, we can use the returned WebSocket object to send and receive messages.

    In Echo method, we can also perform custom code logic to generate and send reply message/notification based on received message(s).

    //received message
    var mes = Encoding.UTF8.GetString(buffer, 0, result.Count);
    
    //code logic here
    //...
    
    //create reply message
    var reply_mes = $"You sent {mes}.";
    
    byte[] reply_mes_buffer = Encoding.UTF8.GetBytes(reply_mes);
    
    await webSocket.SendAsync(new ArraySegment<byte>(reply_mes_buffer, 0, reply_mes.Length), result.MessageType, result.EndOfMessage, CancellationToken.None);
    

    Besides, ASP.NET Core SignalR is an open-source library that simplifies implementing real-time communication functionality. And it does support WebSockets transport and we can easily achieving push messages/notifications to all connected clients or specified subsets of connected clients.

    For more information about ASP.NET Core SignalR, you can check this doc: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-3.1