Implementation of WebSocket protocol based on node _node.js

Source: Internet
Author: User
Tags http request require socket node server

I. Agreement
WebSocket is a protocol of Full-duplex communication between client and server based on TCP, which is defined in HTML5 and is also one of the basic specifications of the next generation WebApp.

It broke through the previous limitations of Ajax, the key is real-time, the server can actively push content to the client! Possible applications are: Multiplayer online games, instant chat, real-time monitoring, Remote Desktop, news server and so on.

For myself, the most I want to try now is what canvas+websocket can do together.

Second, realize
Since the handshake process is a standard HTTP request, there are two options for WebSocket implementations: 1 TCP on implementation, and 2 on existing HTTP software implementations. The advantage of the latter is that you can share existing HTTP server ports without having to implement the authentication functionality and the ability to parse HTTP requests.

The HTTP module of node that is used in this example. (TCP version and all files See attachment)

1, node server-side 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);
  (' 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 regular Web page res.writehead ("{' 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 the Var wrap = function (data) {var FA = 0x00, Fe = 0xff, data = data.tostring () len = 2+buffer.bytelength (d

  ATA), buff = new Buffer (len);
  Buff[0] = FA;
  Buff.write (data,1);
  Buff[len-1] = FE;
return buff;

//Unlock 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 ', function (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 >&G T 8*i & 0xFF})} var challenge = function (key1,key2,head) {var sum = Get_part (key1) + Get_part (key2) + Head.tostri
  Ng (' 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 WebSocket Protocol handshake ', ' upgrade:websocket ', ' connection:upgrade ', ' Sec-websocket-origin: ' + h.origin, ' sec-websocket-location:ws://' + h.host + req.url, ' sec-websocket-protocol:m
  Y-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:

 

Third, details
The WebSocket Protocol implementation on the HTTP protocol is only two steps: shaking hands, sending data.

1. Shake hands
The process of shaking hands is called challenge-response. First, the client initiates an HTTP GET request named upgrade, the server verifies the request, gives 101 responses to indicate acceptance of the protocol escalation, and the handshake is complete.

Chrome Inspector-Beautified Handshake Information:

Request Url:ws://192.168.144.131:4400/pub/chat?q=me
Request Method:get
Status code:101 WebSocket Protocol handshake

Request Headers
Connection:upgrade
host:192.168.144.131:4400
origin:http://localhost:800
SEC-WEBSOCKET-KEY1:P2 G 947T 661 JAf2
Sec-websocket-key2:z z Q ^326 5 9= 7s1 1 7h4
Sec-websocket-protocol::my-custom-chat-protocol
Upgrade:websocket
(Key3): 7c:44:56:ca:1f:19:d2:0a

Response Headers
Connection:upgrade
Sec-websocket-location:ws://192.168.144.131:4400/pub/chat?q=me
sec-websocket-origin:http://localhost:800
Sec-websocket-protocol:my-custom-chat-protocol
Upgrade:websocket
(Challenge Response): 52:df:2c:f4:50:c2:8e:98:14:b7:7d:09:cf:c8:33:40

Request Head Score

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 itself, multiple protocols are separated by a space. (* Another option that is left is cookies)
Sec-websocket-key1: Security Authentication KEY,XHR request cannot forge a request header that starts with ' sec-'.
Sec-websocket-key2: Ditto
Key3: Response body Content, 8 bytes random.
Response Head Section

Sec-websocket-protocol: Must contain the requested child protocol name
Sec-websocket-origin: Must be equal to the source of the request
Sec-websocket-location: Must be equal to the requested address
Challenge Response: Response body content, based on three keys in the request, 16 bytes.
Answer string calculation procedure pseudo code:

Part_1 = Key1 of all digits/key1 Hollow number
part_2 ditto
sum = Big_endian (part_1) +big_endian (part_2) +key3 Challenge_
Response = md5_digest (sum);

Big_endian calculation strategy for 32-bit integers:

# very similar to the RGBA color calculation, from the following function you can see the calculation process
var Big_endian = function (n) {return
  [3,2,1,0].map (function (i) {return n > > 8*i & 0xFF});
Big_endian (0xcc77aaff);
-> [204, 119, 170, 255]

2, send data
The WebSocket API is designed to handle data with events, and the client can obtain the full data as long as the event is notified without having to handle the buffer manually.

In this case, each piece of data is called a frame. In the definition of a specification, its head must start with a 0x00, and the tail property ends at 0xFF, so that at least two bytes of data are sent per time.

In the server implementation, when the data is received, the tail is truncated and the data is sent to the end of the package. The format is as follows:

# "Hello," the original binary representation, the request header and here are all UTF8 code
<buffer E4 bd A0 e5 a5 bd>
# The binary representation after packing.
<buffer E4 BD A0 e5 a5 BD ff>

The above is the entire content of this article, I hope to help you learn.

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.