Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Establishing a simple websocket handshake

Client:

 <script type="text/javascript">
        var socket = new WebSocket('ws://localhost:8183/websession');
        socket.onopen = function () {
            alert('handshake successfully established. May send data now...');
        };
        socket.onclose = function () {
            alert('connection closed');
        };
</script>

server:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Net.Sockets;
 using System.Net;
 using System.IO;


class Program
{
    static void Main(string[] args)
    {
        var listener = new TcpListener(IPAddress.Loopback, 8183);
        listener.Start();
        using (var client = listener.AcceptTcpClient())
        using (var stream = client.GetStream())
        using (var reader = new StreamReader(stream))
        using (var writer = new StreamWriter(stream))
        {
            writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
            writer.WriteLine("Upgrade: WebSocket");
            writer.WriteLine("Connection: Upgrade");
            writer.WriteLine("WebSocket-Origin: http://localhost:8092");
            writer.WriteLine("WebSocket-Location: ws://localhost:8183/websession");
            writer.WriteLine("");
        }
        listener.Stop();
    }
}

the problem is that the connection is never established and the onopen function is never called what may be the problem ?

like image 484
Sora Avatar asked Jan 20 '26 01:01

Sora


1 Answers

Firstly, your "server" seems to be sending the "client" part of the handshake. Secondly, StreamReader and StreamWriter will not help you much; frankly, you would do well just to use the Stream.

Now, the actual handshake is complicated; both client and server need to prove to each-other than they are actually talking web-sockets, and not HTTP. The exact nature of this depends on the version of the protocol you are trying to support (or multiple protocols), but the server is required to perform a maths calculation based on the headers that the client sends; the server sends the answer back in its headers, and this checks that they are talking the same language. Note that this is not a security step: it is a sanity protection step. This is all described in the specification, but an example request / response pair is (from that document):

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

And:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

After which, it drops from HTTP into web-socket protocol, which is binary and unrelated to HTTP. For info, Sec-WebSocket-Accept is the result of the maths calculation, based on the client's Sec-WebSocket-Key.

The next bit of code that you will need is frame support. Again - see the specification. Also keep in mind that this specification is just version 13. If you want to support all clients, you might need to check the older specifications too (there are some subtle tweaks, except for the original original protocol, which was radically different and will require completely different code).

Before writing all this, you might want to look into whether a pre-existing library would be more practical. Windows 8 (and similar versions of server) include web-socket supprt direct in HTTP.SYS, with full support in .NET.

like image 166
Marc Gravell Avatar answered Jan 22 '26 15:01

Marc Gravell