https://github.com/bytedance/node-unix-socket
Unix dgram, seqpacket, etc binding for Node.js.
https://github.com/bytedance/node-unix-socket
dgram nodejs reuseport rust seqpacket-sockets unix-socket
Last synced: 6 months ago
JSON representation
Unix dgram, seqpacket, etc binding for Node.js.
- Host: GitHub
- URL: https://github.com/bytedance/node-unix-socket
- Owner: bytedance
- License: mit
- Created: 2022-07-15T10:33:46.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2024-10-19T09:51:37.000Z (8 months ago)
- Last Synced: 2024-12-10T07:43:40.742Z (7 months ago)
- Topics: dgram, nodejs, reuseport, rust, seqpacket-sockets, unix-socket
- Language: Rust
- Homepage: https://bytedance.github.io/node-unix-socket/
- Size: 409 KB
- Stars: 51
- Watchers: 5
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# node-unix-socket
 
`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.

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