Reputation: 6020
I've recently started playing around with HTML5 WebSockets, and I've got a simple jQuery web client and a console application server. After reading up on the hand shaking here's what I currently have for the client:
var socket = new WebSocket("ws://127.0.0.1:100", ["chat"]);
socket.onopen = function() {
console.log(socket.readyState);
}
This sends the following to my server:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:100
Origin: http://localhost:57944
Sec-WebSocket-Protocol: chat
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: dBQ0epP7wmgHDEJc6Me95Q==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Now, my server code.
First off, I read through the lines sent above from the client, and find the Sec-WebSocket-Key
value and save this to my variable key
.
Then I append the magic number from the Wikipedia article here which is 258EAFA5-E914-47DA-95CA-C5AB0DC85B11. This results in the following code:
key = string.Concat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
using (SHA1 sha1 = SHA1.Create())
{
byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
responseKey = Convert.ToBase64String(hash);
}
Finally, my response key is used in the construction of the message I send back to the client, which is:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: u9guLPph1FeCPuOpFNs4F1b+UqY=
Sec-WebSocket-Protocol: chat
[blank line, as requested in spec]
However, my socket.readyState
goes from 0 to 3 and then fails with the following error WebSocket connection to 'ws://127.0.0.1:100/' failed:
.
I've read that this could be down to my server using an incompatible protocol to the client, but I'm not entirely sure on where to start looking if this is the case. If not, does anyone have any idea how to fix this or where I can go for more information as I'm a little stumped.
21st March 2013
After reading @djc's comment below, I modified my server code to send back the acknowledgement with the following:
using (StreamWriter sw = new StreamWriter(ns, Encoding.UTF8))
{
sw.NewLine = "\r\n\r\n";
// get response and calculate responseKey here (getting bytes as UTF-8 from client)
sw.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
sw.WriteLine("Upgrade: websocket");
sw.WriteLine("Connection: Upgrade");
sw.WriteLine("WebSocket-Origin: http://localhost:57944");
sw.WriteLine("WebSocket-Location: 127.0.0.1:100");
sw.WriteLine("Sec-WebSocket-Accept: " + responseKey);
sw.WriteLine("");
sw.Flush();
}
Well, I no longer get an error on the client - but the 'socket.readyState' remains at 0 and my socket.onopen
block is never fired - although I see the client connection attempt coming through.
Upvotes: 2
Views: 10589
Reputation: 6020
Based on this specification I finally managed to get it working. Here's my client code:
var socket = new WebSocket("ws://localhost:8181/websession", ['chat','superchat']);
socket.onopen = function()
{
$("div#messages").append("<p class=\"event\">Socket is connected.</p>");
socket.send("Thanks!");
};
Seems the inclusion of websession
for cookie management and ['chat','superchat']
protocols were required.
The server:
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8))
{
Dictionary<string, string> headers = new Dictionary<string, string>();
string line = string.Empty;
while ((line = sr.ReadLine()) != string.Empty)
{
string[] tokens = line.Split(new char[] { ':' }, 2);
if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1)
{
headers[tokens[0]] = tokens[1].Trim();
}
}
string responseKey = "";
string key = string.Concat(headers["Sec-WebSocket-Key"], "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
using (SHA1 sha1 = SHA1.Create())
{
byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
responseKey = Convert.ToBase64String(hash);
}
sw.WriteLine("HTTP/1.1 101 Switching Protocols");
sw.WriteLine("Upgrade: websocket");
sw.WriteLine("Connection: Upgrade");
sw.WriteLine("Sec-WebSocket-Accept: " + responseKey);
sw.WriteLine("Sec-WebSocket-Protocol: chat");
sw.WriteLine("");
sw.Flush();
}
Now I'm getting a valid connection, but can't send / receive data with the server - but that's another story I guess.
Upvotes: 3