Asp.net webapi pushes messages to clients through WebSocket to build a service that is both the server and the client

Posted by omprakash on Mon, 21 Oct 2019 17:05:53 +0200

WebSocket is a single TCP Connect to full duplex Communication protocol. WebSocket communication protocol was approved by IETF As standard RFC 6455 and supplemented by RFC7936. WebSocket API Also be W3C Set as standard.

WebSocket makes the data exchange between the client and the server easier, allowing the server to actively push data to the client. In the WebSocket API, the browser and server only need to complete one handshake, and they can directly create a persistent connection and carry out two-way data transmission.

I don't need to talk much. I'll teach you how to communicate.

1. First, create a new UserController to inherit from ApiController, and then write a get method for external calls. Method must be added with [HttpGet], and the code is as follows

[HttpGet]
        public HttpResponseMessage GetConnect(string clientName)
        {
            HttpContext.Current.AcceptWebSocketRequest(ProcessRequest); //Accept the Web Socket request on the server side, and the incoming function serves as the processing function of the Web Socket. After the Web Socket is established, the function will be called. In this function, you can send and receive messages from the Web Socket.

            return Request.CreateResponse(HttpStatusCode.SwitchingProtocols); //Construct a Response that agrees to switch to the Web Socket.
        }
        ///Logging clients
        private static List<WebSocket> _sockets = new List<WebSocket>();
        ///Receiving and sending information
        public async Task ProcessRequest(AspNetWebSocketContext context)
        {
            try
            {
                var socket = context.WebSocket;//The incoming context has the current web socket object
                _sockets.Add(socket);//Add the web socket object to a static list here

                //Enter an infinite loop when web socket close is the end of the loop
                while (true)
                {
                    var buffer = new ArraySegment<byte>(new byte[1024]);
                    var receivedResult = await socket.ReceiveAsync(buffer, CancellationToken.None);//Receiving data asynchronously for web socket
                    if (receivedResult.MessageType == WebSocketMessageType.Close)
                    {
                        await socket.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None);//If the client initiates a close request, ack the client
                        _sockets.Remove(socket);
                        break;
                    }

                    if (socket.State == System.Net.WebSockets.WebSocketState.Open)
                    {
                        string recvMsg = Encoding.UTF8.GetString(buffer.Array, 0, receivedResult.Count);
                        var recvBytes = Encoding.UTF8.GetBytes(recvMsg);
                        var sendBuffer = new ArraySegment<byte>(recvBytes);
                        foreach (var innerSocket in _sockets)//When receiving a text message, broadcast all web socket connections on the current server
                        {
                            if (innerSocket != socket)
                            {
                                await innerSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);//lognet4 logging
            }
        }
    }

2. How to send a message to all clients? Just write another method to send the information to the server as the client, instead of the server polling every time. The code is as follows: this method is written in the same class and can be called directly.

        private readonly ClientWebSocket webSocket = new ClientWebSocket();
        private readonly CancellationToken _cancellation = new CancellationToken();
        ///Client sends message
        private async void SendMsg(object data)
        {
            try
            {
                await webSocket.ConnectAsync(new Uri("ws://localhost:8080/api/User?clientName=" + 123), _cancellation);
                var sendBytes = ObjectToBytes(data);//Data sent
                var bsend = new ArraySegment<byte>(sendBytes);
                await webSocket.SendAsync(bsend, WebSocketMessageType.Binary, true, _cancellation);
                await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "1", _cancellation);
                webSocket.Dispose();//Remember to release it or there will be many connections on the server.
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);//lognet4 logging
            }
        }

3. The client code of the web version is as follows

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
 <title></title>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.11.3.min.js"></script>
 <script>
 var ws;
 $().ready(function () {
  $('#conn').click(function () {
  ws = new WebSocket('ws://localhost:8080' + '/api/user?clientName='+'456');
  $('#MSG '). Append (' < p > connecting < / P > ');
 
  ws.onopen = function () {
   $('#MSG '). Append (' < p > connected < / P > ');
  }
  ws.onmessage = function (evt) {
   $('#msg').append('<p>' + evt.data + '</p>');
  }
  ws.onerror = function (evt) {
   $('#msg').append('<p>' + JSON.stringify(evt) + '</p>');
  }
  ws.onclose = function () {
   $('#MSG '). Append (' < p > closed < / P > ');
  }
  });
 
  $('#close').click(function () {
  ws.close();
  });
 
  $('#send').click(function () {
  if (ws.readyState == WebSocket.OPEN) {
   ws.send($("#to").val() + "|" + $('#content').val());
  }
  else {
   $('#tips').text('connection closed ');
  }
  });
 
 });
 </script>
</head>
<body>
 <div>
 <input id="user" type="text" />
 <input id="conn" type="button" value="Connect" />
 <input id="close" type="button" value="Close"/><br />
 <span id="tips"></span>
 <input id="content" type="text" />
 <input id="send" type="button" value="Send out"/><br />
 <input id="to" type="text" />Target user
 <div id="msg">
 </div>
 </div>
</body>
</html>

4. The code of C ා console client is as follows

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WebSocketClient
{
    class Program
    {
        static ClientWebSocket _webSocket = new ClientWebSocket();
        static CancellationToken _cancellation = new CancellationToken();
        static void Main(string[] args)
        {
            WebSocket();
            Console.Read();
        }

        public static async void WebSocket()
        {
            try
            {

                //Establish connection
                var url = "ws://localhost:8080/api/User?clientName=" + 456;

                await _webSocket.ConnectAsync(new Uri(url), _cancellation);
                while (true)
                {
                    var result = new byte[1024];
                    await _webSocket.ReceiveAsync(new ArraySegment<byte>(result), new CancellationToken());//Accept data
                    var str = Encoding.UTF8.GetString(result, 0, result.Length);
                    Console.WriteLine(str);//Print to console
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

 

Topics: socket encoding JQuery JSON