Implementation of node. JS's WebSocket protocol

Source: Internet
Author: User

WebSocket is no longer something new, and there are third-party modules that can be implemented on node. js as well as socket.io. But the individual has the code neat, really can not stand on the HTML page more than one line of the following code:

<script src= ' http://192.168.0.143:4000/socket.io/socket.io.js ' ></script>

Moreover, the project to achieve the effect is to interact with the canvas, and some things are still packaged with the socket is relatively simple, so they set foot on the road to explore the websocket.

By the way share under my labor, not perfect, because the project on my own is engaged in ... The process is a bit slow (after demo download, node starts nodecanvas.js)

GitHub:Nodecanvas

Since the code in GitHub is annotated, I'll just say the approximate implementation steps of WebSocket.


Browser end:
 websocket = new websocket ("ws://"  + ip +  ": 3000/");    Various events of      //websocket         websocket.onopen  = function  ()  {             Console.log ("Connected to websocket server.");         };                  websocket.onclose = function  ()  {             console.log ("Disconnected");             //zwei.close ();         };        websocket.onmessage = function  ( EVT) &NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSp; console.log (' retrieved data from server:  '  + evt.data);             //zwei.msg ();         };                 websocket.onerror = function  (EVT)  {             console.log (' error occured:  '  + evt.data);             //zwei.error ();        };                 websocket.send ("Zwei");

There are a few things you should be aware of when you look at it. The things that send can be objects or arrays, but not multiple, only one, and all of them are hexadecimal when they are received on the server side.


Server side:

The server side began to compare the egg pain, engaged me for nearly one weeks, because did not get an HTTP head what, the understanding of this aspect is not too much .... The total is divided into 2 parts. The first one is the upgrade of the Protocol, so that the 2-terminal realizes that the protocol is upgraded to WebSocket. The second part is decoding (described later).

The first part, directly on the code:

  var key = req.headers[' Sec-websocket-key '],             steam = new buffer (0),             resHeaders,             MAGIC_STRING =  ' 258eafa5-e914-47da-95ca-c5ab0dc85b11 ',             websocket;        key =  require (' crypto ')             .createhash (' SHA1 ')             .update (key + MAGIC_ STRING)             .digest (' base64 ');         resHeaders = [              ' HTTP/1.1 101 switching protocols ',              ' Upgrade: websocket ',             ' Connection: upgrade ',             ' sec-websocket-accept:  '  + key        ];         resheaders = resheaders.concat (',  '). Join (' \ r \ n ');         socket.setnodelay (True);         socket.write (resheaders);

This part is the handshake process. First the client initiates an HTTP GET request named upgrade, the server verifies the request, gives a 101 response to accept the protocol upgrade, and the handshake is complete.

Because the WebSocket protocol implementation on top of the HTTP protocol is only two steps: handshake, send data. So even if the WebSocket connection is established.

The function of each part of the above code can be self-Baidu, or see << in- depth shallow out of node. js>> and I've mostly learned it from this book.


Part II:

here I stuck for a long time, because the websocket transfer to the server side, the data is in hexadecimal format, and is still encrypted, although decoding is regular but also toss me for a long, after the Cnode forum saw someone wrote a decoding, tried the next can, After the change of his code (after all, my basic knowledge is not good, the bit operation is helpless), This 2 code is still good, a decoding, an encryption for the transfer back to browser ( The server side data is automatically decoded when the browser side is received, so do not decode), directly affixed to the code:

Processing mask Buffer Stream (receive) Function decodeframe (frame)  {    if  (frame.length  &LT;&NBSP;2)  {        return null;    }     var counter = 0,        fin_ Offset = 7,        opcode_offset = parseint (1111, &NBSP;2),    //15        mask_offset = 7,         payload_len_offset = parseint (1111111,&NBSP;2),    //127        FIN ,         Opcode ,        MASK ,         Payload_len,        buffer,         Masking_key,        i,         j;    FIN = frame[counter] >> fin_offset;     opcode = frame[counter++] & opcode_offset;    mask  = frame[counter] >> mask_offset;    Payload_len =  frame[counter++] & payload_len_offset;    payload_len === 126  &&  (Payload_len = frame.readuint16be (counter))  &&  (counter &NBSP;+=&NBSP;2);    payload_len === 127 &&  (Payload_len  = frame.readuint32be (counter + 4)  &&  (counter += 8);     buffer = new buffer (Payload_len);    if  (MASK)  {       &nbSp; masking_key = frame.slice (counter, counter + 4);         counter += 4;        for  (i  = 0; i < payload_len; i++)  {             j = i % 4;             buffer[i] = frame[counter + i] ^ Masking_key[j];         }    }    if  ( Frame.length < counter + payload_len)  {         return undefined;    }    frame = frame.slice ( Counter + payload_len);    return {         fin: fin,  &nBsp;     opcode: opcode,        mask:  MASK,        Payload_len: Payload_len,         payload_data: buffer,        frame:  frame    };} Processing mask buffer Stream (send) Function encodeframe (frame)  {    var preBytes =  [],        paybytes = new buffer (frame. Payload_data),        datalength = paybytes.length;     prebytes.push (frame. FIN&NBSP;&LT;&LT;&NBSP;7)  + frame. Opcode);    if  (datalength < 126)  {         prebytes.push (frame. MASK&NBSP;&LT;&LT;&NBSP;7)  + datalength);     }    else if  (Datalength < math.pow (2, 16))  {         prebytes.push (             (frame . MASK&NBSP;&LT;&LT;&NBSP;7)  + 126,              (DATALENGTH&NBSP;&AMP;&AMP;&NBSP;0XFF00)  >> 8,             dataLength && 0xFF         );    }    else {         prebytes.push (            ) (frame. MASK&NBSP;&LT;&LT;&NBSP;7)  + 127,             0, 0, 0, 0,             ( Datalength && 0xFF000000)  >> 24,             ( datalength && 0xff0000)  >> 16,              (DATALENGTH&NBSP;&AMP;&AMP;&NBSP;0XFF00)  >> 8,             dataLength && 0xFF         );     }    prebytes = new  buffer (prebytes);     return buffer.concat ([prebytes, paybytes]);}


Implementation of node. JS's WebSocket protocol

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.