Skip to content
cWS is modified version of the uWebsockets v0.14 with some minor tweaks in C++ code and complete rewrite of JS code.
C++ C TypeScript JavaScript Python Batchfile Other
Branch: master
Clone or download
stop5 and goriunov add node API-Version 79
fixes the build when running node 13.
Latest commit 74ac863 Nov 22, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
dist Improves typings of .on('connection') callback - add upgrade request (#… Nov 8, 2019
lib Improves typings of .on('connection') callback - add upgrade request (#… Nov 8, 2019
src Fix issue with using reserved code Sep 8, 2019
test Fix issue with using reserved code Sep 8, 2019
.gitignore Optimize c++ module, added benchs Jul 8, 2018
.npmignore Move to new ts-builder Sep 13, 2018
CHANGELOG.md Add PR links to CHANGELOG Nov 8, 2019
LICENSE Fix text Oct 18, 2018
Makefile
README.md Minor README cleanup Jul 29, 2019
binding.gyp Update binding.gyp Dec 30, 2018
make.bat Use integer instead of double, fix windows bat Apr 25, 2019
package.json Release 0.16.0 Nov 8, 2019
tsbuild.json Fix broadcast typings, fix external modules, deploy version 0.4.1 Sep 17, 2018
tslint.json Improves typings of .on('connection') callback - add upgrade request (#… Nov 8, 2019

README.md

ClusterWS/cWS Implementation

Modified version of uWebSockets v0.14

This is modified version of the uWebSockets v0.14 with some minor tweaks in C++ code and complete rewrite of JS code to TypeScript. Original software is available in uWebSockets v0.14 repository.

npm version

This repository is based on the uWebSockets v0.14 therefore has two licence ClusterWS MIT and Alex Hultman ZLIB.

Big thanks to SirAnthony for ssl workaround (has been taken from SirAnthony's uWebSockets fork).

All breaking changes from released version will be included in CHANGELOG.md

Consider to support development:

Documentation

Installation

npm i @clusterws/cws

WebSocket Server

To find about what types and parameters are accepted please check index.d.ts file.

const { WebSocketServer } = require('@clusterws/cws');

const server = new WebSocketServer({
  /**
   *  Available server configurations
   * 
   *  path?: string,
   *  port?: number,
   *  host?: string;
   *  server?: HTTP.Server | HTTPS.Server,
   *  noDelay?: boolean,
   *  maxPayload?: number,
   *  perMessageDeflate?: {
   *     serverNoContextTakeover: boolean
   *  };
   *  verifyClient?: (info: ConnectionInfo, next: Listener) => void
   * 
   * For more types check dist/index.d.ts file
  */
});


/**
 * To accept WebSocket connections use on('connection') listener
 * 
 * socket: WebSocket client
 * upgReq: upgrade request
*/
server.on('connection', (socket, upgReq) => {
    /** get remoteAddress info */ 
    let address = socket._socket;

    /**
      * on 'message' will be called when this client sends new message
      * 
      * msg: string | binary
    */
    socket.on('message', (msg) => { });

    /**
      * on 'close' will be called when connections is closed
      * 
      * code?: number, 
      * reason?: string
    */
    socket.on('close', (code, reason) => { });

    /**
      * on 'error' will be called websocket connection has some problems
      * 
      * err: Error 
    */
    socket.on('error', (err) => { });

    /**
      * on 'pong' will be called when client response with pong to the server's ping message
    */
    socket.on('pong', () => { });

    /**
      * on 'ping' will only be called on clint side when ping is received
    */
    socket.on('ping', () => { });

    /**
      * 'send' method is used to send messages to the client / server
      * 
      * message: string | binary
      * options?: { binary?: boolean, compress?: boolean }
      * cb?: function 
      * 
      * message type is detected automatically except
      * if you force string type with `{ binary: false }`
    */
    socket.send(message, options, cb);


    /**
      * 'ping' method is to to manually send ping to the client
    */
    socket.ping();

    /**
      * 'terminate' method is to force close connection (usually to remove dead sockets)
    */
    socket.terminate();

    /**
      * 'close' method is to close connection in clean / correct way
      * 
      * code: number (close code)
      * reason: string (the reason to close this socket)
    */
    socket.close(code, reason);
});



/**
  * 'startAutoPing' will enable auto ping for all connected clients 
  * without any need for custom ping implementation
  * 
  * interval: number
  * appLevelPing: boolean (default false)
  * 
  * `interval` specifies how often ping should be send 
  * usually it should be around 20000 ms (20s)
  * 
  * `appLevelPing` if true will enable ping in application level usually used for clients like
  * browsers which do not expose `onping` and `onping` listeners and you need to track if server connection
  * is still active, to make it work correctly you required to implement custom handle in you client side
  * check `Handle AppLevelPing In Browser Example` at the end of readme for more information
*/
server.startAutoPing(interval, appLevelPing);


/**
 * `broadcast` method will send your message to all connected clients
 * 
 * message: string | binary,
 * options?: { binary: true | false }
*/
server.broadcast(message, options);

/** will close websocket server and call callback function after everything is done */
server.close(callback);


/** 
 * on error listener will be called when there is some issue with server creation or
 * upgrading socket connection properly
 */
server.on('error', (err, socket) => { })

WebSocket Client

Websocket client pretty much has the same things as socket parameter passed in the server (above section) on new connection, below docs will cover mostly things which were not covered in above section.

const { WebSocket } = require('@clusterws/cws');

/** this will connect to specify url */ 
const socket = new WebSocket('ws://url:port');

/** for more information about this listeners and functions check above section 
 *  as client and server have similar signatures
 */ 
socket.on('open', () => { })
socket.on('message', (msg) => { });
socket.on('error', (err) => { });
socket.on('close', (code, reason) => { });
socket.on('ping', () => { });
socket.on('pong', () => { });
socket.ping();
socket.send(msg);
socket.terminate();
socket.close(code, reason);

/** 
 * also websocket client support browser websocket signature 
 * 
 * Note that there is no onping and onpong as browsers dont expose this
 * functions to the users.
 * 
 * to use onping and onpong use:
 * 
 * socket.on('pong', () => { });
 * socket.on('ping', () => { });
 */ 
socket.onopen = () => {};
socket.onmessage = (msg) => {};
socket.onerror = (error) => {};
socket.onclose = (code, reason) => {};

Additional Configuration/Examples

Replace EventEmitter

CWS uses custom lightweight version of EventEmitter which may not be suitable for everyone, to replace event emitter you can use global cws configuration:

// replace cws EventEmitter with Node.js default one
global.cws = {
  EventEmitter: require('events').EventEmitter
}

// It is important to import cws after!
const { WebSocket } = require('@clusterws/cws');

Handle AppLevelPing In Browser Example

This is just an example of handling app level ping, pong from the client side which does not have onping and onpong listeners available such as browsers.

Note if your clients have onping and onpong listeners (or similar) do not send appLevelPing ping from the server.

const PING = 57;
const PONG = new Uint8Array(['A'.charCodeAt()]);

socket.binaryType = 'arraybuffer' // Do not forget to set to `arraybuffer`

socket.onmessage = function (message) {
    // check if message is not string 
    if (typeof message.data !== 'string') {
        // transform it to Unit Array
        let buffer = new Uint8Array(message.data);

        // Check if it is actually ping from the server
        if ( buffer.length === 1 && buffer[0] === PING) {
            // you can also emit that ping has been received to you client :)
            // if it is then send back to the server pong response
            return socket.send(PONG);
        }
    }

    // process with your logic
}
You can’t perform that action at this time.