i'm trying create c# websocket server don't seem working. have server accepts tcpclient, receives http request client , tries send http response html5 websocket handshake can completed.
i believe there wrong handshake server sends client. read draft (websocket 76 draft) states @ end of handshake response has given 2 keys given. response gets calculated server.
this code:
static void main(string[] args) { int port = 8181; ipaddress localaddr = ipaddress.loopback; tcplistener server = new tcplistener(localaddr, port); server.start(); // buffer reading data byte[] receivedbytes = new byte[256]; string data = null; // enter listening loop. while (true) { console.writeline("waiting connection..."); // perform blocking call accept requests. // user server.acceptsocket() here. tcpclient client = server.accepttcpclient(); console.writeline("connected!\n"); data = null; // stream object reading , writing networkstream stream = client.getstream(); int i; // loop receive data sent client. while ((i = stream.read(receivedbytes, 0, receivedbytes.length)) != 0) { // translate data bytes ascii string. data = system.text.encoding.utf8.getstring(receivedbytes, 0, i); console.writeline("received:"); console.writeline(data); byte[] response_token = hashresponse(data); string handshake = "http/1.1 101 websocket protocol handshake\r\n" + "upgrade: websocket\r\n" + "connection: upgrade\r\n" + "sec-websocket-origin: http://localhost\r\n" + "sec-websocket-location: ws://localhost:8181/websession\r\n" + "\r\n"; byte[] writtenbytes = encoding.utf8.getbytes(handshake); stream.write(writtenbytes, 0, writtenbytes.length); stream.write(response_token, 0, response_token.length); console.writeline("send:"); console.writeline(handshake); string strhash = encoding.utf8.getstring(response_token); console.writeline(strhash); } } } static byte[] hashresponse(string receiveddata) { string strdel = "\r\n"; char[] delimeter = strdel.tochararray(); string key1 = null; string key2 = null; string hash = null; md5 md5 = md5.create(); string[] lines = receiveddata.split(delimeter); key1 = lines[10].substring(20); key2 = lines[12].substring(20); hash = lines[16]; int64 numberskey1 = convert.toint64(string.join(null, regex.split(key1, "[^\\d]"))); int64 numberskey2 = convert.toint64(string.join(null, regex.split(key2, "[^\\d]"))); int64 numberspaces1 = countspaces(key1); int64 numberspaces2 = countspaces(key2); int dividedkey1 = (int) (numberskey1 / numberspaces1); int dividedkey2 = (int) (numberskey2 / numberspaces2); byte[] encodedkey1 = encoding.utf8.getbytes(dividedkey1.tostring()); byte[] encodedkey2 = encoding.utf8.getbytes(dividedkey2.tostring()); byte[] encodedhash = encoding.utf8.getbytes(hash); byte[] combined = encoding.utf8.getbytes(dividedkey1.tostring() + dividedkey2.tostring() + hash); byte[] responsehash = md5.computehash(combined); return responsehash; } static int countspaces(string key) { int counter = 0; char[] chararray = key.tochararray(); foreach (char c in chararray) { if (c.equals(' ')) counter++; } return counter; }
the html page (which named test.html) i'm using testing hosted apache webserver runs on computer access browsing (in chrome) http://localhost/test.html
does have clue i'm doing wrong because i'm getting quite desperate.
thanks in advance
dennis
here's sample server wrote illustrating handshake phase in accordance draft-ietf-hybi-thewebsocketprotocol-00:
using system; using system.collections.generic; using system.io; using system.net; using system.net.sockets; using system.security.cryptography; using system.text; using system.text.regularexpressions; class program { static void main(string[] args) { var listener = new tcplistener(ipaddress.loopback, 8080); listener.start(); while (true) { using (var client = listener.accepttcpclient()) using (var stream = client.getstream()) { var headers = new dictionary<string, string>(); string line = string.empty; while ((line = readline(stream)) != string.empty) { var tokens = line.split(new char[] { ':' }, 2); if (!string.isnullorwhitespace(line) && tokens.length > 1) { headers[tokens[0]] = tokens[1].trim(); } } var key = new byte[8]; stream.read(key, 0, key.length); var key1 = headers["sec-websocket-key1"]; var key2 = headers["sec-websocket-key2"]; var numberskey1 = convert.toint64(string.join(null, regex.split(key1, "[^\\d]"))); var numberskey2 = convert.toint64(string.join(null, regex.split(key2, "[^\\d]"))); var numberspaces1 = countspaces(key1); var numberspaces2 = countspaces(key2); var part1 = (int)(numberskey1 / numberspaces1); var part2 = (int)(numberskey2 / numberspaces2); var result = new list<byte>(); result.addrange(getbigendianbytes(part1)); result.addrange(getbigendianbytes(part2)); result.addrange(key); var response = "http/1.1 101 websocket protocol handshake" + environment.newline + "upgrade: websocket" + environment.newline + "connection: upgrade" + environment.newline + "sec-websocket-origin: " + headers["origin"] + environment.newline + "sec-websocket-location: ws://localhost:8080/websession" + environment.newline + environment.newline; var bufferedresponse = encoding.utf8.getbytes(response); stream.write(bufferedresponse, 0, bufferedresponse.length); using (var md5 = md5.create()) { var handshake = md5.computehash(result.toarray()); stream.write(handshake, 0, handshake.length); } } } } static int countspaces(string key) { return key.length - key.replace(" ", string.empty).length; } static string readline(stream stream) { var sb = new stringbuilder(); var buffer = new list<byte>(); while (true) { buffer.add((byte)stream.readbyte()); var line = encoding.ascii.getstring(buffer.toarray()); if (line.endswith(environment.newline)) { return line.substring(0, line.length - 2); } } } static byte[] getbigendianbytes(int value) { var bytes = 4; var buffer = new byte[bytes]; int num = bytes - 1; (int = 0; < bytes; i++) { buffer[num - i] = (byte)(value & 0xffl); value = value >> 8; } return buffer; } }
and sample client:
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="text/javascript"> var socket = new websocket('ws://localhost:8080/websession'); socket.onopen = function() { alert('handshake established. may send data now...'); }; socket.onclose = function() { alert('connection closed'); }; </script> </head> <body> </body> </html>
Comments
Post a Comment