📜 ⬆️ ⬇️

WebSocket & ASP.NET

html5 In this topic, I want to tell you how to organize a WebSocket connection between a browser that supports WebSocket and an ASP.NET application.
The article describes how to make a connection and send a message to a connected client. Also, at the end of the article, there is a link to the source code of the working application.

The article and the application are just an example of how this all works, and how ASP.NET and WebSockets can be linked, and are unlikely to claim implementation guidance in their current form, but it demonstrates well the basics and can be improved.

Why do we need WebSockets and what are their advantages, I think I don’t need to tell. Personally, I think that they are very lacking in order to make full-fledged client-side applications in JavaScript without Comet tricks (excellent article here ) or periodic requests.
But specifically, this technology seriously interested me when looking for a solution to a small “problem” of working with Comet in the Chrome browser.

When organizing using Comet technology, some browsers, such as Chrome, behave in such a way that it seems as though the page is constantly loading, the same Chrome writes “waiting for a request” and the cursor always remains in a waiting state.
Chrome Cursor with Comet

This is of course unpleasant.
And simply, why use a workaround when there is a more suitable technology for this and an opportunity to study it.

So the connection itself. On the client side (JavaScript), the browser provides a special WebSocket class.
Here is a description of it from here.

Using it, we open a connection to the server and subscribe to the necessary events, as well as send messages to the server after the connection.

var sock;
function connectToServer() {
try {
sock = new WebSocket( "ws://localhost:8181/websock" );
sock.onopen = sockOpen;
sock.onerror = sockError;
sock.onclose = sockClosed;
sock.onmessage = sockMessage;
} catch (e) {
log( "error:" + e);

* This source code was highlighted with Source Code Highlighter .

As can be seen from the code above, our server will wait for connections at localhost: 8181.
In this example, all functions subscribers simply display information in a text field, and we do not send anything to the server. After connecting, it is quite simple to do this, but in this example it will only complicate things a little.

So server. Since the ASP.NET application / website only works when processing requests, and we need to constantly wait for connections, we need to start a separate thread. Let's do this in Global.asax. The stream and server will be dealt with by our special classic.
void Application_Start( object sender, EventArgs e)

void Application_End( object sender, EventArgs e)

* This source code was highlighted with Source Code Highlighter .

In the Start function, we simply start the Thread, which will wait for the connection, and in the End we clean up after ourselves. All this can be viewed in more detail in the source code, which I will give at the end of the article.

So, then the code of the main function itself, but first I will briefly tell you what will happen, what would be easier to navigate.
Here is the code itself.
public static void Listen()<br> {<br> // <br> Listener = new TcpListener(IPAddress.Loopback, PortNumber);<br> Listener.Start();<br><br> while ( true )<br> {<br> // <br> using (Socket client = Listener.AcceptSocket()) <br> using (NetworkStream stream = new NetworkStream(client)) <br> using (StreamReader reader = new StreamReader(stream)) <br> using (StreamWriter writer = new StreamWriter(stream)) <br> {<br><br> string clientHandshake = String .Empty; <br> string currentRead = null ; <br> string clientOrigin = "" ; <br><br> while (currentRead != "" )<br> {<br> // handshake <br> currentRead = reader.ReadLine();<br> clientHandshake += currentRead + Environment.NewLine;<br><br> // <br> if (currentRead.StartsWith( "Origin" ))<br> {<br> // <br> int valueStartIndex = currentRead.IndexOf( ':' ) + 1;<br> clientOrigin = currentRead.Substring(valueStartIndex, currentRead.Length - valueStartIndex);<br> }<br> }<br><br> // (Handshake) <br> writer.WriteLine( "HTTP/1.1 101 Web Socket Protocol Handshake" );<br> writer.WriteLine( "Upgrade: WebSocket" );<br> writer.WriteLine( "Connection: Upgrade" );<br><br> // Origin . <br> // " ", , <br> // , . <br> writer.WriteLine( String .Format( "WebSocket-Origin: {0}" , clientOrigin));<br> writer.WriteLine( "WebSocket-Location: ws://localhost:8181/websock" );<br> writer.WriteLine( "" );<br> writer.Flush();<br><br> // / . <br> Thread.Sleep(100);<br> <br> // <br> byte [] first = new byte [] { 0x00 };<br> byte [] last = new byte [] { 0xFF };<br> <br> // ( ) <br> client.Send(first);<br><br> // Hello World <br> client.Send( Encoding .UTF8.GetBytes( "Hello world!" ));<br><br> // ( ) <br> client.Send(last);<br> }<br> }<br> } <br><br> * This source code was highlighted with Source Code Highlighter .

And here are the promised sources.

This is the simplest example, it has flaws, such as the lack of multithreading in processing clients. And also, it still has to be improved, for example, to provide access to a user session.

I would be glad if the article is liked and helps someone, I will try to develop the topic and write more.

UPD: In the comments, we noticed that the implementation for the previous edition is 75, the current 76, in which security was added. I will try to make a version that will work with both editions, but apparently, not anymore today.
For those who asked to share the groundwork, I poured everything here . In theory, everything should work but does not work :), where it is a joint but the brain does not notice it anymore.

UPD2: As promised, here is a version that supports both versions 75 and 76.

Source: https://habr.com/ru/post/100669/

All Articles