Use node to implement the websocket protocol and nodewebsocket Protocol

Source: Internet
Author: User
Tags node server

Use node to implement the websocket protocol and nodewebsocket Protocol
Protocol

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.

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)

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 ');}

Browser client code:

Details

The websocket Protocol over http implements only two steps: handshaking and sending data.

Handshake

The handshake process is called challenge-response. First, the client initiates an http get request named Upgrade. The server verifies the request and returns a 101 response to accept the Protocol Upgrade. The handshake is complete.

Handshaking information beautified by chrome inspector:

Request URL:ws://192.168.144.131:4400/pub/chat?q=meRequest Method:GETStatus Code:101 WebSocket Protocol HandshakeRequest HeadersConnection:UpgradeHost:192.168.144.131:4400Origin:http://localhost:800Sec-WebSocket-Key1:p2    G 947T 80  661 jAf2Sec-WebSocket-Key2:z Z Q ^326 5 9= 7s1  1 7H4Sec-WebSocket-Protocol::my-custom-chat-protocolUpgrade:WebSocket(Key3):7C:44:56:CA:1F:19:D2:0AResponse HeadersConnection:UpgradeSec-WebSocket-Location:ws://192.168.144.131:4400/pub/chat?q=meSec-WebSocket-Origin:http://localhost:800Sec-WebSocket-Protocol:my-custom-chat-protocolUpgrade:WebSocket(Challenge Response):52:DF:2C:F4:50:C2:8E:98:14:B7:7D:09:CF:C8:33:40

Request Header

  • Host: websocket server Host
  • Connection: Connection Type
  • Upgrade: Protocol Upgrade type
  • Origin: Access Source
  • Sec-WebSocket-Protocol: Optional. Sub-Protocol name, defined by the application. Multiple protocols are separated by spaces. (* The remaining option is cookie)
  • Sec-WebSocket-Key1: Security Authentication key, xhr requests cannot forge request headers starting with 'sec.
  • Sec-WebSocket-Key2: Same as above
  • Key3: response body content, 8-byte random.

Response Header

  • Sec-WebSocket-Protocol: The request's sub-Protocol name must be included.
  • Sec-WebSocket-Origin: must be equal to the request source
  • Sec-WebSocket-Location: must be equal to the request address
  • Challenge Response: the content of the Response body, measured in 16 bytes based on the three keys in the request.

Pseudo code for string response calculation:

Part_1 = All numbers in key1/number of spaces in key1 part_2 same as sum = big_endian (part_1) + big_endian (part_2) + key3challenge_response = md5_digest (sum );

The calculation policy of the 32-bit integer big_endian:

# It is similar to rgba color calculation. The following function shows the calculation process var big_endian = function (n) {return [,]. map (function (I) {return n> 8 * I & 0xff});} big_endian (0xcc77aaff); //-> [204,119,170,255]
Send data

The WebSocket API is designed to process data with events. The client can obtain complete data as long as it receives Event Notifications without manual processing of the buffer.

In this case, each piece of data is called a frame. In the standard definition, its header must start with 0x00 and its tail attribute end with 0 x ff, so that each data is sent to a few two bytes.

In server implementation, when receiving data, you must cut the head and tail, while sending data is to wrap the head and tail. The format is as follows:

# The original binary representation of 'Hello'. The request header and here are both UTF-8 encoded <Buffer e4 bd a0 e5 a5 bd> # The packaged binary representation. <Buffer 00 e4 bd a0 e5 a5 bd ff>
Reference

Websocket draft: http://www.whatwg.org/specs/web-socket-protocol/

W3 websocket api: http://dev.w3.org/html5/websockets/

Whatwg webapp specification: http://www.whatwg.org/specs/web-apps/current-work/

Interesting proof of Interaction: Zero-knowledge proofs

Attachment

View or download: https://gist.github.com/1066475

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.