This article mainly introduces information about how to implement the websocket protocol based on node. For more information, see
I. Agreement
WebSocket is a protocol for full-duplex communication between clients and servers based on TCP. It is defined in HTML5 and is also one of the basic specifications of the next-generation webapp.
It breaks through the limitations of AJAX earlier. The key lies in real-time performance. The server can actively push content to the client! Possible applications include multiplayer online games, instant chats, real-time monitoring, remote desktop, and news servers.
For myself, what I want to do most is what can be combined by canvas + websocket.
II. Implementation
Because the handshake process is a standard HTTP request, websocket has two options: 1) TCP implementation; 2) Existing HTTP software implementation. The latter's advantage is that it can share the existing HTTP server port and does not need to implement the authentication function and parse the HTTP Request function again.
The HTTP module of node used in this example. (For TCP versions and all files, see the attachment)
1. node server code:
Var http = require ('http'); var url = require ('url'); // var mime = require ('mime '); var crypto = require ('crypto'); var port = 4400; var server = http. createServer (); server. listen (port, function () {console. log ('server is running on localhost: ', port); server. on ('connection', function (s) {console. log ('on connection', s );}). on ('request', onrequest ). on ('upgrade', onupgrade) ;}); var onrequest = function (Req, res) {console. log (Object. keys (req), req. url, req ['upgrade']); if (! Req. upgrade) {// non-upgrade request Selection: interrupt or provide normal Web res. writeHead (200, {'content-type': 'text/plain '}); res. write ('websocket server works! ');} Res. end (); return ;}; var onupgrade = function (req, sock, head) {// console. log ('method: ', Object. keys (sock); if (req. headers. upgrade! = 'Websocket ') {console. warn ('illegal connection'); sock. end (); return;} bind_sock_event (sock); try {handshake (req, sock, head);} catch (e) {console. error (e); sock. end () ;}}; // wrap the frame to be sent var wrap = function (data) {var fa = 0x00, fe = 0xff, data = data. toString () len = 2 + Buffer. byteLength (data), buff = new Buffer (len); buff [0] = fa; buff. write (data, 1); buff [len-1] = fe; return buff;} // unlock the received frame var unwrap = function (Data) {return data. slice (1, data. length-1);} var bind_sock_event = function (sock) {sock. on ('data', function (buffer) {var data = unwrap (buffer); console. log ('socket receive data: ', buffer, data,' \ n> '+ data); // send ('Hello html5,' + Date. now () sock. emit ('send', data );}). on ('close', function () {console. log ('socket close ');}). on ('end', function () {console. log ('socket end ');}). on ('send', functio N (data) {// custom event sock. write (wrap (data), 'binary ') ;}; var get_part = function (key) {var empty = '', spaces = key. replace (/\ S/g, empty ). length, part = key. replace (/\ D/g, empty); if (! Spaces) throw {message: 'wrong key: '+ key, name: 'handshakeerror'} return get_big_endian (part/spaces);} var get_big_endian = function (n) {return String. fromCharCode. apply (null, [3, 2, 1, 0]. map (function (I) {return n> 8 * I & 0xff})} var challenge = function (key1, key2, head) {var sum = get_part (key1) + get_part (key2) + head. toString ('binary '); return crypto. createHash ('md5 '). update (sum ). digest ('binary ');} var handshake = function (req, sock, head) {var output = [], h = req. headers, br = '\ r \ n'; // header output. push ('HTTP/1.1 101 WebSocket Protocol Handshake ', 'upgrade: WebSocket', 'Connection: upgrade', 'sec-WebSocket-Origin: '+ h. origin, 'sec-WebSocket-Location: ws: // '+ h. host + req. url, 'sec-WebSocket-Protocol: my-custom-chat-Protocol' + br); // body var c = challenge (h ['sec-websocket-key1 '], h ['sec-websocket-key2 '], head); output. push (c); sock. write (output. join (br), 'binary ');}
2. browser client code:
WebSocket Demo
Send