Using middleware to manage WebSocket in ASP.

Source: Internet
Author: User
Tags httpcontext
Introduced

ASP. NET Core signalr is a useful library that simplifies the management of real-time communication in Web applications. However, I prefer to use websockets because I want to be more flexible and compatible with any WebSocket client.

In the Microsoft documentation, I found a good example of websockets work. It is still a management connection so that it can broadcast messages from one connection to another, which is signalr out-of-the-box functionality. Expect this logic to be very complex and I want to remove it from the startup class.

Background

To read websockets support in ASP. NET core, you can view it here. Read this link if you want to learn about middleware and how to write it in ASP.

Code use

First, you must add the Microsoft.AspNetCore.WebSockets package to your project.

Now you can create an extension method and a class to manage websockets:

 Public Static classwebsocketextensions{ Public StaticIapplicationbuilder Usecustomwebsocketmanager ( ThisIapplicationbuilder app) {       returnApp. Usemiddleware<customwebsocketmanager>(); }} Public classcustomwebsocketmanager{Private ReadOnlyrequestdelegate _next;  PublicCustomwebsocketmanager (requestdelegate next) {_next=Next; }     Public AsyncTask Invoke (HttpContext context, Icustomwebsocketfactory wsfactory, Icustomwebsocketmessagehandler wsmhandler) { if(Context. Request.path = ="/ws")        {            if(context. Websockets.iswebsocketrequest) {stringUsername = context. request.query["u"]; if(!string. IsNullOrEmpty (username)) {WebSocket WebSocket=awaitcontext.                    Websockets.acceptwebsocketasync (); Customwebsocket Userwebsocket=NewCustomwebsocket () {WebSocket=WebSocket, Username=username};                    Wsfactory.add (Userwebsocket); awaitwsmhandler.sendinitialmessages (Userwebsocket); awaitListen (context, Userwebsocket, wsfactory, Wsmhandler); }            }            Else{context. Response.statuscode= -; }        }        await_next (context); }    Private AsyncTask Listen (HttpContext context, Customwebsocket Userwebsocket, Icustomwebsocketfactory wsfactory, Icustomwebsocketmessagehandler wsmhandler) {WebSocket WebSocket=Userwebsocket.websocket; varBuffer =New byte[1024x768*4]; Websocketreceiveresult result=awaitWebsocket.receiveasync (Newarraysegment<byte>(buffer), cancellationtoken.none);  while(!result. Closestatus.hasvalue) {awaitwsmhandler.handlemessage (result, buffer, userwebsocket, wsfactory); Buffer=New byte[1024x768*4]; Result=awaitWebsocket.receiveasync (Newarraysegment<byte>(buffer), cancellationtoken.none);        } wsfactory.remove (Userwebsocket.username); awaitWebsocket.closeasync (result. Closestatus.value, result.    Closestatusdescription, Cancellationtoken.none); }}

In this case, the WebSockets request always contains "/ws" in the URL. The query string contains the parameter u for the user name that is used to associate WebSocket with the logged-on user.

Customwebsocket is a class that contains websocket and user names:

 Public class customwebsocket{   publicgetset;}     Public string Get Set ; }}

I also created a custom WebSocket message:

class customwebsocketmessage{   publicstringgetset;}     Public Get Set ; }     Public string Get Set ; }     Public Get Set ; }}

Where type is an enumeration of the different types of messages you might have.

In the startup class, you must register the following services:

Services. Addsingleton<icustomwebsocketfactory, customwebsocketfactory>(); services. Addsingleton<icustomwebsocketmessagehandler, customwebsocketmessagehandler> ();

Customwebsocketfactory is responsible for collecting the WebSockets list of connections:

 Public Interfaceicustomwebsocketfactory{voidAdd (Customwebsocket UWS); voidRemove (stringusername); List<CustomWebSocket>All (); List<CustomWebSocket>Others (Customwebsocket client); Customwebsocket Client (stringusername);} Public classcustomwebsocketfactory:icustomwebsocketfactory{List<CustomWebSocket>List;  Publiccustomwebsocketfactory () {List=NewList<customwebsocket>(); }    Public voidAdd (Customwebsocket UWS) {list.add (UWS); }   //When disconnect    Public voidRemove (stringusername)   {List.remove (Client (username)); }    PublicList<customwebsocket>All () {returnList; }       PublicList<customwebsocket>Others (Customwebsocket client) {returnList.where (c = c.username! =client. Username).   ToList (); }     PublicCustomwebsocket Client (stringusername) {      returnList.first (C=>c.username = =username); }}

Customwebsocketmessagehandler contains logic about the message (that is, any message needs to be sent at the time of the connection and how to react to the incoming message)

 Public Interfaceicustomwebsocketmessagehandler{Task sendinitialmessages (Customwebsocket userwebsocket); Task handlemessage (websocketreceiveresult result,byte[] buffer, Customwebsocket userwebsocket, icustomwebsocketfactory wsfactory); Task Broadcastothers (byte[] buffer, Customwebsocket userwebsocket, icustomwebsocketfactory wsfactory); Task Broadcastall (byte[] buffer, Customwebsocket userwebsocket, Icustomwebsocketfactory wsfactory);} Public classcustomwebsocketmessagehandler:icustomwebsocketmessagehandler{ Public AsyncTask sendinitialmessages (customwebsocket userwebsocket) {WebSocket WebSocket=Userwebsocket.websocket; varmsg =NewCustomwebsocketmessage {messagdatetime=DateTime.Now, Type=Wsmessagetype.anytype, Text=Anytext, Username="system"      }; stringSerialisedmessage =jsonconvert.serializeobject (msg); byte[] bytes =Encoding.ASCII.GetBytes (serialisedmessage); awaitWebsocket.sendasync (Newarraysegment<byte> (Bytes,0, bytes. Length), Websocketmessagetype.text,true, Cancellationtoken.none); }    Public AsyncTask handlemessage (websocketreceiveresult result,byte[] buffer, Customwebsocket userwebsocket, Icustomwebsocketfactory wsfactory) {      stringmsg =Encoding.ASCII.GetString (buffer); Try      {         varmessage = jsonconvert.deserializeobject<customwebsocketmessage>(msg); if(Message. Type = =wsmessagetype.anytype) {awaitbroadcastothers (buffer, userwebsocket, wsfactory); }      }      Catch(Exception e) {awaitUserWebSocket.WebSocket.SendAsync (Newarraysegment<byte> (Buffer,0, result. Count), result. MessageType, result.      Endofmessage, Cancellationtoken.none); }   }    Public AsyncTask Broadcastothers (byte[] buffer, Customwebsocket userwebsocket, Icustomwebsocketfactory wsfactory) {      varothers =wsfactory.others (Userwebsocket); foreach(varUWsinchothers) {         awaitUWs. Websocket.sendasync (Newarraysegment<byte> (Buffer,0, buffer. Length), Websocketmessagetype.text,true, Cancellationtoken.none); }   }    Public AsyncTask Broadcastall (byte[] buffer, Customwebsocket userwebsocket, Icustomwebsocketfactory wsfactory) {      varall =Wsfactory.all (); foreach(varUWsinchAll ) {         awaitUWs. Websocket.sendasync (Newarraysegment<byte> (Buffer,0, buffer. Length), Websocketmessagetype.text,true, Cancellationtoken.none); }   }}

Finally, add the following in the startup class of the Configure method:

var New websocketoptions () {    = timespan.fromseconds (+),    41024x768  };app. Usewebsockets (websocketoptions); app. Usecustomwebsocketmanager ();

In this way, the Starup class remains clean, and the logic of managing websockets can be extended so that you can organize it flexibly to your liking. Just like this article. Using middleware to manage WebSocket in ASP.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.