npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@encharm/cws

v4.4.1

Published

cWS - fast C++ WebSocket implementation for Node.js

Downloads

167

Readme

Important Notes

  • Consider using latest version of uWebSockets if you do not need compatibility with ws or a multi-process architecture.

  • This repository is a fork of ClusterWS/cWS

  • Prior, this repository was a fork of uWebSockets v0.14 therefore has two licence MIT and ZLIB

Supported Node Versions (SSL)

This table is true if you run ssl directly with cws (Node.js). In case if you use proxy for example nginx, cws can be run on bigger coverage.

| cWS Version | Node 14 | Node 16 | Node 18 | Node 20 | |-------------|----------|---------|-------------------| | 4.4.x | X | X | X | X |

Node <14 are supported with @clusterws/cws.

Documentation

Useful links

Table of Contents

Installation

npm i @encharm/cws

Websocket Client

Typings: dist/client.d.ts

Import cws WebSocket:

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

Connect to WebSocket server:

const socket = new WebSocket(/* ws server endpoint **/);

Event on open is triggered when server accepts connection and this connection is ready to perform other actions:

socket.on('open', () => { });
// or like browser interface
socket.onopen = () => { };

Event on error is triggered if there is an error with the connection:

socket.on('error', (err) => { });
// or like browser interface
socket.onerror = (err) => { };

Event on close is triggered when connection has been closed:

// code: number and reason: string are optional
socket.on('close', (code, reason) => { });
// or like browser interface
socket.onclose = (code, reason) => { };

Event on message is triggered when client receives message(s):

// receives string or binary

socket.on('message', (message) => { });
// or like browser interface
socket.onmessage = (message) => { };

Event ping is triggered when other side sends ping to check if connection still active:

socket.on('ping', () => { });

Event pong is triggered after ping has been sent and it received back conformation:

socket.on('pong', () => { })

To send message use send function:

// send accepts string or binary
// will automatically identify type
socket.send(msg);

// will overwrite/specify message type to string (does not transform data to specified type)
socket.send(msg, { binary: false });

// will overwrite/specify message type to binary (does not transform data to specified type)
socket.send(msg, { binary: true });

// will call callback after message sent or errored
socket.send(msg, null, (err) => { });

To close connection you can use close or terminate methods:

// clean close code and reason are optional
socket.close(code, reason);
// destroy socket 
socket.terminate()

Use ping function to manually send ping:

socket.ping();
// now just wait for `pong` event

To get current socket ready state can use readyState getter:

socket.readyState; // -> OPEN (1) or CLOSED (3)

// check if socket open can be done by
if(socket.readyState === socket.OPEN) {}

// check if socket closed can be done by
if(socket.readyState === socket.CLOSED) {}

To find out number of buffered (and not yet sent) bytes:

socket.bufferedAmount;
// useful for implementing back-pressure

To get addresses use _socket getter:

socket._socket;

// Returns some thing like (all fields could be undefined):
// {
//  remotePort,
//  remoteAddress,
//  remoteFamily
// }

For more information check typings (*.d.ts) files in dist folder

Websocket Server

Typings: dist/server.d.ts

Import cws WebSocket:

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

Create WebSocket server:

const wsServer = new WebSocket.Server({ 
  /**
   * port?: number (creates server and listens on provided port)
   * host?: string (provide host if necessary with port)
   * path?: string (url at which accept ws connections)
   * server?: server (provide already existing server)
   * noDelay?: boolean (set socket no delay)
   * noServer?: boolean (use this when upgrade done outside of cws)
   * maxPayload?: number 
   * perMessageDeflate?: boolean | { serverNoContextTakeover: boolean;}
   * verifyClient?: (info: ConnectionInfo, next: VerifyClientNext) => void (use to allow or decline connections)
   **/ 
 }, () => {
  // callback called when server is ready
  // is not called when `noServer: true` or `server` is provided
  // from outside
});

Event on connection is triggered when new client is connected to the server:

// `ws` is websocket client all available options 
// can be found in `Websocket Client` section above
// `req` is http upgrade request
wsServer.on('connection', (ws, req) => {})

Event on error is triggered when server has some issues and noServer is false:

// on error event will NOT include httpServer errors IF
// server was passed under server parameter { server: httpServer },
// you can register on 'error' listener directly on passed server
wsServer.on('error', (err) => { })

Event on close is triggered after you call wsServer.close() function, if cb is provided both cb and on close listener will be triggered:

wsServer.on('close', () => { })

To get all connected clients use clients getter:

wsServer.clients;

// loop thought all clients:
wsServer.clients.forEach((ws) => { });

// get number of clients:
wsServer.clients.length;

To send message to all connected clients use broadcast method:

// broadcast string
wsServer.broadcast(message);

// broadcast binary
wsServer.broadcast(message, { binary: true });

cWS supports auto ping with startAutoPing function:

wsServer.startAutoPing(interval, appLevel);

// send ping to each client every 10s and destroy client if no pong received 
wsServer.startAutoPing(10000);

// pass true as second parameter to run app level ping
// this is mainly used for browser to track pings at client level
// as they do not expose on ping listener 
// look for browser client side implementation at the bottom
// `Handle App Level Ping In Browser (example)`
wsServer.startAutoPing(10000, true);

To stop server use close function:

wsServer.close(() => {
  // triggered after server has been stopped
})

handleUpgrade is function which is commonly used together with noServer (same as ws module)

const wss = new WebSocket.Server({ noServer: true });
const server = http.createServer();

wss.on('connection', (ws, req) => { })

server.on('upgrade', (request, socket, head) => {
  wss.handleUpgrade(request, socket, head, (ws) => {
      wss.emit('connection', ws, request);
  });
});

For more information check typings (*.d.ts) files in dist folder

Secure WebSocket

You can use wss:// with cws by providing https server to cws and setting secureProtocol on https options:

const { readFileSync } = require('fs');
const { createServer }  = require('https');
const { WebSocket, secureProtocol  } = require('@encharm/cws');

const options = {
  key: readFileSync(/** path to key */),
  cert: readFileSync(/** path to certificate */),
  secureProtocol
  // ...other Node HTTPS options
};

const server = createServer(options);
const wsServer = new WebSocket.Server({ server });
// your secure ws is ready (do your usual things)

server.listen(port, () => {
  console.log('Server is running');
})

For more detail example check examples folder

Handle App Level Ping In Browser (example)

Handling custom App level ping, pong from the client side which does not have onping and onpong listeners available such as browsers.

Note if all your clients have onping and onpong listeners do not send appLevelPing ping from the server. If you enable appLevelPing you will need to implement similar handler for every client library which connects to the server.

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

socket.binaryType = 'arraybuffer';

socket.onmessage = function (message) {
    // note actually sent message in
    // browser default WebSocket is under `message.data`

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

        // Check if it is actually ping from the server
        if (buffer.length === 1 && buffer[0] === PING) {
            // this is definitely `ping` event you can call custom on ping handler 
            // also must send back immediately pong to the server 
            // otherwise server will disconnect this client
            return socket.send(PONG);
        }
    }

    // process with your logic
}