ASP.NET Core SignalR - WebSockets Deep Dive

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in the introductory video i've explained that signalr solves the problem of real-time communication does so by establishing a duplex connection or at least an illusion of one uses three primary protocols for this websockets is the first one then it's server sent events and then it's long polling today we're going to take a look at websockets we're going to try to understand what the heck is a websocket is it's its own thing is it http and we're just going to take a look at some examples of how websockets can be used in asp.net core and just generally c-sharp remember all the links are in the description so if you want the source code or the link to the full playlist go ahead and find it there let's take a look at the websockets project here and here we will find only the configure method that's really been implemented we also have the list of connections which i'll get to in a second we have static files we initialize web sockets you don't really need to understand what this does we will take a look at more under the hood implementation towards the end of the video but in the asp.net core style this is just going to use a bunch of services under the hood to allow us to use websockets which is what signalr uses as well otherwise what we're doing is we are just mapping an endpoint and to maintain that duplex connection that sort of you just establish a websocket connection and it just sits there what we're gonna do is imagine this code could be in a controller but we have the context and from this context and the context is the http context right if i hover over it it's the http context it has a websockets property and what we're doing is on this endpoint we're going to accept a websocket connection and once we do all i'm doing here is i'm just adding it to this list which will be apparent why i'm doing it when i do a little demo but the main overview of what is happening here is we're trying to receive some data just so we can enter this loop that just so we understand that the connection is successful and then we just have an index to kind of say all right we're sending different messages so the two things that we're doing is we're constructing a message and we're sending it to all connections this is the first part the second part is from the websocket we receive a message right so we receive a message and we just print it to the console and we do it in a loop right nothing too complicated send messages to all clients and receive messages and log them the way that we receive messages is that we're using this buffer so we're reading things into the buffer and then we're just parsing it and printing out to the console in the end we might close the connection and remove it from the list right so we're doing a little bit of cleanup at the end here but otherwise the code here is pretty straightforward you don't really need to see me type this out manually then we have the index.html page and this is just we need to serve this using static files the index.html page is super simple we create a websocket connection on this url here we have again an index just so we know that once the connection is open we can create an interval function and every two seconds we are going to send some data i'm going to expect to see data space some kind of index to be received on this end so here we'll be seeing received data one two three four etcetera on this end on the browser what we're gonna see is again data received but it will be in the console log in the browser so here again we're receiving data and we're sending data and really it's just to understand that the stuff that signalr has built you can build it yourself now there might be a question around websockets some people do understand it some people don't understand it but essentially browsers have to implement these features there will be a standard and they will call it websockets and websockets is a way of communicating kind of like the english language or any other language as long as i say these things in the in this order with the following pronunciations you understand what i'm saying websockets are the same thing http is the same thing i say these things in this order and you understand what i'm saying as long as you've done the correct implementation now because this is a standard web browsers they have to implement these on their own so this is why when you look for web browser features some browsers will support them and some browsers won't so you have to check websockets itself as a technology just a communication protocol the class that you're seeing here is an interface that's described in the protocol the implementation for it lives in the browser and if you are wondering if the fetch api or any other classes like local storage have to go from the same process yes yes they do nevertheless we have our websocket connection and i already went over what happens here let's start it up let's see what happens right so i have the terminal which is going to do net run let's open up the website so we only have the index.html page which i'm going to open in a second but we're recording what we want to see is the network tab let's land on the index page here we'll see the websocket connection being opened let's click on that and here we'll see messages so we're receiving message index zero if we come back to our app here we will see that the message index and some number is being generated here and then is being sent to all clients on the other end you will see here in the console we're printing the message that we're sending here on an interval so data and some number is being printed here and received is oh basically this message hopefully it's nothing too complicated we're taking turns sending data and then receiving some data the important thing is that this connection is not being severed we're not having many http requests being sent back and forth so we're sending stuff and then we're waiting for a reply we're sending stuff and then we're waiting for a reply we're not doing that right we are just sending messages as they come along the only thing that may be a little bit illusionary and be like why are we not using regular http is that i'm choosing to do this in order i can do this out of order i can receive 30 messages and then only send one okay that can happen no problem if we look at the headers the initial connection actually looks like an http request we have headers we have response headers and you know i mean the only things is like the schema is a little bit different instead of https we have ws status code is 101 and a couple of things we'll find out why but sec website website websocket can upgrade a websocket kind of basically make it a websocket connection but let's uh meditate here for a little bit more we're basically sending messages two ways let's uh take a look at what else we can do right so again sequentially receiving and sending messages what i wanna do is let do let's duplicate this tab and again i'm gonna open this here and by the way in the console we're still printing these numbers but what you will see now is we're actually receiving twice the amount of messages so you'll see receive twice and send off one received wipes and send of one and that's because of this loop here where for every time we loop i want to send the message to all the clients and each connection has its own state of this endpoint okay and you can think of this as how signalr essentially keeps track of all the clients and then sends off messages to all of them and again if i duplicate another connection again this is going to be receiving all the previous messages from all the other clients that are currently going and i too bad i don't have the network tab here but essentially you will see here again this message indexes 6 25 and 86 at the moment you see which one is sending these messages because this is the oldest one so it's sending the biggest number this is the middle child and this is the youngest child and those will be sending their respective numbers those these numbers are essentially correlating to how old these are but hopefully you get the picture of communication and let's come back here and i'll just close it what we've seen there is we have a web browser session it establishes a connection and that connection just lives on you can send messages both ways you don't have to make a request and then receive data you can receive some data and then send some data what we've noticed there is if you've ever used signal our tried to use signalr is we're not really calling any methods that is signalr functionality where you will have a hub and you will have a couple of messages and we will go over that later the data received and hub method mapping happens separately and that's a signalr thing here what i want you to understand is you make a connection and then you're just able to send it both ways the client tracking or the connection tracking again that's a signalr thing and i had to partially implement this myself if i want to send data to currently all connected websockets i have to keep track of these connections and then i have to send data to them manually right so just because the server has two websocket connections that doesn't mean the data is automatically sent to all of them right so that's kind of like maybe clearing a little bit of fog for signalr now let's go a little bit deeper because what happens here is we do not use websockets and some magic happens and i'm going to say we're going to go a little bit deeper which is where we have the custom server so let's close startup we're not going to look at specifically what use websockets does but let's open up this program and i've used a bunch of documentation again from mozilla just of their specification how they describe how to build backend endpoints but what we're going to do here is we're going to do what the kestrel server does so the thing that hosts asp.net core it creates a socket connection we bind to an ap address and then we're going to start listening what i'm not doing here is i'm not keeping track of all the connections and i'm not allowing multiple connections i'm only going to have one connection and really that's just an implementation detail i don't want to spend too much time on this example but for the socket on which we're listening we're going to accept a connection that is going to be its own individual socket okay so this is the socket that we're now referring to network stream is just for us to be able to read from that socket we then have a buffer and the buffer again when you're working with streams that's just how you do it and i'm sorry this is not a tutorial on buffers but essentially what we do is we load data into a buffer which is a byte array so we're just reading some bytes the browser is going to send some bytes and we're just going to read some bytes right just zeros and ones we will then parse the byte into a string and if string contains a get that means the websocket connection is trying to get established it's making a get request just regular get http request now what we're doing is we're looking for sec websocket key so that little header that was appended there you basically the way that they describe it i hopefully understood it correctly but you basically make an accept websocket header and what you do is i'm essentially constructing a manually an http response which i then get the bytes off and then i just write it back to the stream and i flush it so i return a response but now i have a while loop and i don't end here so the connection is never closed and what i do is i just go ahead and read more bytes and this is where a little bit or maybe not even a little bit the most confusing part happens the message that the websocket connection is receiving on the server side so browser is sending the message that message is encoded so you have to do a little bit of decoding again another link here on the format of how the message is encoded and decoded but essentially and this is actually this will be worth looking at this in just a second so we can have say it so this is basically what the packet looks like and we will see it a little bit more closely so let's go ahead and first run this so we're going to open up the server let's do run here and you're not going to get any messages because well it's not an asp in a core application however what we're going to do is we're going to open index.html in this file browser we're gonna drag it over to the browser and we're just gonna open it here so what happens here now is i mean you can't really see it but let's come back here and we're still sending data and we're receiving it and we can see that the connection is open before this what we will see is what is being printed here is if i slowly scroll up to here is this first request that we're seeing here so just a regular get http request and all we're doing is we're just not closing it at the end and we're able to receive data and we will be able to send data back to it as well however i just chose not to do it in this example as for the data parsing and decoding this is just a little process that you have to go through but let's take a look at this bit here the first byte is an operation code and described here it basically just either has no meaning on basically says it's a text data or binary data etc but i skip that very first byte and i basically say i mean it doesn't matter i'm just going to ignore it the second thing that i'm doing is i'm reading in the length of the message so if you watched my readers video about how we communicate with readers i mean the same kind of thing happens here we got to do a little bit of a a little bit of a malarkey here so this is the first eight bits this is the first byte the second byte here what we have is the the first bit of the byte we have a mask and then the payload length so the mask this first bit here is what we're doing here is we're basically just taking this byte and we're subtracting it from the same value as if it would this would have been one and the rest is zero what this basically tells us is the payload length up to 126 so from zero to 125 if it's over that we need to use a different protocol so i have comments here but essentially i'm only supporting messages that are under the 126 byte length so what happens here is if the first bit would be zero we would get a bit flip and then it basically means that the first byte is not the thing that represents the length it will be the next couple of bytes yeah after it it gets a little bit easier maybe not so easier but in the next or byte you get a key or a mask that it can be referred to and you just do x or decoding i'm just saying xor decoding but i don't know if it's even worth explaining this algorithm and i don't know if i'm actually doing a good job because you i'd say the only way that you can really understand it is if you're going to go step by step debug it but essentially we get a length we get a key we create a new array where this is the data that we're going to parse where then we'll we're then having a length where what we're doing is we're offsetting by six because we want to skip the first bit with the first byte the second byte and the four bytes which contain the key and we just want to leave those alone because the rest of the thing is the payload so we slowly iterate through that we xor it by the bit and the key and we slowly iterate through those one by one and then in the end we fill up the data that will be the data and then we print it so i mean rambling on this is all the this is how we basically decode and receive the data this is what signalr and use websockets will ultimately use underneath the covers now here you will see this example and a lot of this stuff looks already pretty complicated i don't really write code like this at work either i mean this stuff is already built for me you will see that to make many connection work a lot more work will need to go into this as well if you're not satisfied with the sensor and you want to go deeper you're going to have to do that on your own because you're going to go into the land of native c or c plus implementations of how does windows expose this or how does the runtime implement this because and by the runtime i mean the dotnetruntime.net runtime has to have an implementation that talks to the operating system about how to use this hardware to open up these sockets or to start listening to these sockets hopefully you can kind of bury the hatchet there it's making a connection that allows you to talk both ways it is still pretty much an http connection although it's just one that isn't closed and the reason we can distinct it between regular http request and the websocket one is because of a couple of headers and the response that we make and it all has to comply with the websocket specification here i think that is pretty much all i have on the websockets if you are still confused or have any questions about them do leave them in the comments section or ask them on my discord server otherwise thank you very much for watching and have a good day
Info
Channel: Raw Coding
Views: 6,498
Rating: undefined out of 5
Keywords: asp.net core, signalr, tutorial, guide, example, explained, c#, real time, websockets, deep dive
Id: 6W5gmRgmbuc
Channel Id: undefined
Length: 17min 14sec (1034 seconds)
Published: Tue Oct 12 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.