UNPKG

node-unix-socket

Version:

node-unix-socket allows you to use SO_REUSEPORT, SOCK_SEQPACKET, SOCK_DGRAM in Node.js.

187 lines (134 loc) 5.08 kB
# node-unix-socket ![npm_bandage](https://img.shields.io/npm/v/node-unix-socket) ![github_ci_status](https://github.com/bytedance/node-unix-socket/workflows/CI/badge.svg) `node-unix-socket` allows you to use some nonblocking unix sockets that are currently not supported by Node.js native modules, including: - unix seqpacket(`SOCK_SEQPACKET`) sockets - unix datagram(`SOCK_DGRAM`) sockets - Using `SO_REUSEPORT` enabled TCP [net.Server](https://nodejs.org/dist/latest-v16.x/docs/api/net.html#class-netserver) `node-unix-socket` is a [napi-rs](https://napi.rs/) based [Node.js addons](https://nodejs.org/docs/latest-v16.x/api/addons.html) and: - This lib bases on n-api and is pre-compiled so that it doesn't require compilation environments if yours is pre-built supported. - This lib won't introduce any other asynchronous runtimes as it uses [libuv](https://libuv.org/) inside Node.js. We use `SOCK_SEQPACKET` sockets for in our internal APM. ## Tested Platforms & Node.js |Platform|Node.js|DgramSocket|Seqpacket| |---|---|---|---| |x64 Linux|12 + LTS|✅|✅| |x64 Darwin|12 + LTS|✅|| |aarch64 Darwin|12 + LTS|✅|| ## Installation ``` npm i node-unix-socket ``` ## API Documents [API Documents](https://bytedance.github.io/node-unix-socket/) ## Seqpacket Sockets `SOCK_SEQPACKET` sockets are like `SOCK_STREAM` sockets while they keep message boundaries. Note that `SOCK_SEQPACKET` sockets don't work on MacOS. ### Example [Online Example](https://codesandbox.io/s/node-unix-seqpacket-socket-n3hd8l?file=/index.js) ```js const { SeqpacketServer, SeqpacketSocket } = require('node-unix-socket'); const os = require('os'); const path = require('path'); const fs = require('fs'); const bindPath = path.resolve(os.tmpdir(), './my_seqpacket.sock'); try { fs.unlinkSync(bindPath); } catch (e) {} const server = new SeqpacketServer(); server.listen(bindPath); server.on('connection', (socket) => { socket.on('data', (buf) => { console.log('received', buf.toString()); }); }); const client = new SeqpacketSocket(); client.connect(bindPath, () => { const data = ['hello, ', 'w', 'o', 'r', 'l', 'd']; for (const str of data) { client.write(Buffer.from(str)); } client.end(); }); ``` ## Dgram Sockets ### Example [Online Example](https://codesandbox.io/s/node-unix-dgram-socket-76cyyu?file=/index.js) ```js const { DgramSocket } = require('node-unix-socket'); const os = require('os'); const path = require('path'); const fs = require('fs'); const path1 = path.resolve(os.tmpdir(), './my_dgram_1.sock'); const path2 = path.resolve(os.tmpdir(), './my_dgram_2.sock'); try { fs.unlinkSync(path1); fs.unlinkSync(path2); } catch (err) {} const socket1 = new DgramSocket(); const socket2 = new DgramSocket(); socket1.bind(path1); socket2.bind(path2); socket2.on('data', (data, remoteAddr) => { console.log(`socket2 received: ${data.toString()}`); // echo socket2.sendTo(data, 0, data.length, remoteAddr); }); socket1.on('data', (data) => { console.log(`socket1 received: ${data.toString()}`); }); setInterval(() => { const buf = Buffer.from('hello'); socket1.sendTo(buf, 0, buf.length, path2); }, 1000); ``` ## `SO_REUSEPORT` enabled TCP net.Server The [cluster](https://nodejs.org/dist/latest-v18.x/docs/api/cluster.html) module share server ports by accepting new connections in the primary process and distributing them to worker processes. With `SO_REUSEPORT`, sockets will be distributed by kernel instead, and which should be more performant especially for scenario of having a lot of short-lived connections. For example, the arrow in the image below shows cpu usage of a PM2 primary process which we found in our environment. ![cpu_usage](./resource/cpu_usage.png) Note that `SO_REUSEPORT` might behave much differently across operating systems. See this [post](https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ) for more information. ### Example [Online Http Server Example](https://codesandbox.io/s/node-so-reuseport-net-server-no9mvm?file=/index.js) ```js const { createReuseportFd } = require('node-unix-socket'); const { Server, Socket } = require('net'); const port = 8080; const host = '0.0.0.0'; // create multple servers listening to a same host, port. for (let i = 0; i < 2; i += 1) { const fd = createReuseportFd(port, host); const server = new Server((socket) => { socket.on('data', (buf) => { console.log(`server ${i} received:`, buf); // echo socket.write(buf); }); }); server.listen( { fd, }, () => { console.log(`server ${i} is listening on ${port}`); } ); } setInterval(() => { const client = new Socket(); client.on('data', (buf) => { console.log('client received:', buf); client.destroy(); }); client.connect(port, host, () => { client.write(Buffer.from('hello')); }); }, 1000); ``` ## CONTRIBUTING [CONTRIBUTING.md](./CONTRIBUTING.md) ## Development 1. Setup rust and Node.js. 2. Modify the code. 2. `npm run build && npm run test` ## LICENSE MIT