Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of Interprocess communication in Node.js through a UNIX domain socket
/*
**
** Example of Interprocess communication in Node.js through a UNIX domain socket
**
** Usage:
** server> MODE=server node ipc.example.js
** client> MODE=client node ipc.example.js
**
*/
var net = require('net'),
fs = require('fs'),
connections = {},
server, client, mode
;
// prevent duplicate exit messages
var SHUTDOWN = false;
// Our socket
const SOCKETFILE = '/tmp/unix.sock';
// For simplicity of demonstration, both ends in this one file
switch(process.env["MODE"] || process.env["mode"]){
case "server": mode = "server"; break;
case "client": mode = "client"; break;
default: console.error("Mode not set"); process.exit(1);
}
console.info('Loading interprocess communications test');
console.info(' Mode: %s \n Socket: %s \n Process: %s',mode,SOCKETFILE,process.pid);
function createServer(socket){
console.log('Creating server.');
var server = net.createServer(function(stream) {
console.log('Connection acknowledged.');
// Store all connections so we can terminate them if the server closes.
// An object is better than an array for these.
var self = Date.now();
connections[self] = (stream);
stream.on('end', function() {
console.log('Client disconnected.');
delete connections[self];
});
// Messages are buffers. use toString
stream.on('data', function(msg) {
msg = msg.toString();
if(msg === '__snootbooped'){
console.log("Client's snoot confirmed booped.");
return;
}
console.log('Client:', msg);
if(msg === 'foo'){
stream.write('bar');
}
if(msg === 'baz'){
stream.write('qux');
}
if(msg === 'here come dat boi'){
stream.write('Kill yourself.');
}
});
})
.listen(socket)
.on('connection', function(socket){
console.log('Client connected.');
console.log('Sending boop.');
socket.write('__boop');
//console.log(Object.keys(socket));
})
;
return server;
}
if(mode === "server"){
// check for failed cleanup
console.log('Checking for leftover socket.');
fs.stat(SOCKETFILE, function (err, stats) {
if (err) {
// start server
console.log('No leftover socket found.');
server = createServer(SOCKETFILE); return;
}
// remove file then start server
console.log('Removing leftover socket.')
fs.unlink(SOCKETFILE, function(err){
if(err){
// This should never happen.
console.error(err); process.exit(0);
}
server = createServer(SOCKETFILE); return;
});
});
// close all connections when the user does CTRL-C
function cleanup(){
if(!SHUTDOWN){ SHUTDOWN = true;
console.log('\n',"Terminating.",'\n');
if(Object.keys(connections).length){
let clients = Object.keys(connections);
while(clients.length){
let client = clients.pop();
connections[client].write('__disconnect');
connections[client].end();
}
}
server.close();
process.exit(0);
}
}
process.on('SIGINT', cleanup);
}
if(mode === "client"){
// Connect to server.
console.log("Connecting to server.");
client = net.createConnection(SOCKETFILE)
.on('connect', ()=>{
console.log("Connected.");
})
// Messages are buffers. use toString
.on('data', function(data) {
data = data.toString();
if(data === '__boop'){
console.info('Server sent boop. Confirming our snoot is booped.');
client.write('__snootbooped');
return;
}
if(data === '__disconnect'){
console.log('Server disconnected.')
return cleanup();
}
// Generic message handler
console.info('Server:', data)
})
.on('error', function(data) {
console.error('Server not active.'); process.exit(1);
})
;
// Handle input from stdin.
var inputbuffer = "";
process.stdin.on("data", function (data) {
inputbuffer += data;
if (inputbuffer.indexOf("\n") !== -1) {
var line = inputbuffer.substring(0, inputbuffer.indexOf("\n"));
inputbuffer = inputbuffer.substring(inputbuffer.indexOf("\n") + 1);
// Let the client escape
if(line === 'exit'){ return cleanup(); }
if(line === 'quit'){ return cleanup(); }
client.write(line);
}
});
function cleanup(){
if(!SHUTDOWN){ SHUTDOWN = true;
console.log('\n',"Terminating.",'\n');
client.end();
process.exit(0);
}
}
process.on('SIGINT', cleanup);
}
@ORESoftware

This comment has been minimized.

Copy link

commented May 20, 2018

this will only work for one client, if there is more than 1 client, the clients will get mixed up, AFAICT.

old school IPC sucks, use network protocols instead - TCP etc.

@jschlesser

This comment has been minimized.

Copy link

commented Jun 8, 2018

When you are processing the data events in the client or the server are the events guaranteed to get whole messages and only 1 message? Would you need to keep a buffer around across multiple data calls in case you get '__b' on one event and 'oop' on another and might you get '__boop__disconn' in one data event and 'ect' in another?

@bbartolome

This comment has been minimized.

Copy link

commented Jun 14, 2018

Thanks for the example @Xaekai

I've used it to explore IPC over socket files between Docker containers: https://github.com/bbartolome/ipc-test

@hinell

This comment has been minimized.

Copy link

commented Aug 3, 2018

@bbartolome So, what are results?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.