JsonSocket
JsonSocket
is a very easy way to send JSON over a socket using either TCP or UNIX sockets. JsonSocket
uses a decorator pattern
to expose extra methods and events on instances of net.Socket
.
These methods and events makes it straightforward to send bidirectional JSON messages of any kind and size.
Installation
You can install JsonSocket
using Node Package Manager (npm):
npm install json-socket
Or add it to your package.json
file, like this:
{
...
"dependencies": {
"json-socket": "*"
}
...
}
And then run:
npm install
Usage
JsonSocket
relies on Node.js' built-in net
package. Everytime you have an instance
of net.Socket
you simply wrap in an instance of JsonSocket
.
Simple client/server example
Here is a simple example where a client can connect to the server and send two numbers (a and b) that the server multiplies
and sends back the result.
Server
var net = require('net'),
JsonSocket = require('json-socket');
var port = 9838;
var server = net.createServer();
server.listen(port);
server.on('connection', function(socket) {
socket = new JsonSocket(socket);
socket.on('message', function(message) {
var result = message.a + message.b;
socket.sendEndMessage({result: result});
});
});
Client
var net = require('net'),
JsonSocket = require('json-socket');
var port = 9838;
var host = '127.0.0.1';
var socket = new JsonSocket(new net.Socket());
socket.connect(port, host);
socket.on('connect', function() {
socket.sendMessage({a: 5, b: 7});
socket.on('message', function(message) {
console.log('The result is: '+message.result);
});
});
Streaming example
Here is an example of a server that can stream square numbers. A client can connect and send a start
command which should
also include a beginAt
value, i.e. which number should be squared first. Then the server streams a square every second,
until the client sends a stop
command.
Server
var net = require('net'),
JsonSocket = require('json-socket');
var port = 9838;
var server = net.createServer();
server.listen(port);
server.on('connection', function(socket) {
socket = new JsonSocket(socket);
var n;
var isRunning = false;
var streatTimeout;
socket.on('message', function(message) {
if (message.command == 'start') {
if (!isRunning) {
n = message.beginAt || 1;
isRunning = true;
streamInterval = setInterval(function() {
socket.sendMessage(n * n);
n++;
}, 1000);
}
} else if (message.command == 'stop') {
if (isRunning) {
isRunning = false;
clearInterval(streamInterval);
}
}
});
});
Client
var net = require('net'),
JsonSocket = require('json-socket');
var port = 9838;
var host = '127.0.0.1';
var socket = new JsonSocket(new net.Socket());
socket.connect(port, host);
socket.on('connect', function() {
socket.sendMessage({command: 'start', beginAt: 10});
socket.on('message', function(square) {
console.log(square);
if (square > 200) {
socket.sendMessage({command: 'stop'});
}
});
});
Will output:
100
121
144
169
196
225
Sending a single message
JsonSocket has two helper methods that are useful if you just need to send a single message and you don't need the socket
to stay open.
The second method is JsonSocket.sendSingleMessage
. It sends a single message and closes the connection instantly.
Use this if you need to send a server a message, but you don't need any response.
var JsonSocket = require('json-socket');
JsonSocket.sendSingleMessage(port, host, {type: 'ping'}, function(err) {
if (err) {
throw err;
}
console.log('Pinged '+host+' on port '+port);
});
The second method is JsonSocket.sendSingleMessageAndReceive
. It sends a single message, waits for a single response
message from the server and closes the connection right after.
Use this if you need to send a server a message, and get a response, but you don't need the connection to stay open.
var JsonSocket = require('json-socket');
JsonSocket.sendSingleMessageAndReceive(port, host, {type: 'ping'}, function(err, message) {
if (err) {
throw err;
}
console.log('Server said: '+message.type);
});
Message formats
The messages can be any Javascript object that can be converted to JSON:
- Strings
- Numbers
- Booleans
- Objects
- Arrays
- Anything!
Since JsonSocket
is a decorator of net.Socket
, it supports all methods that net.Socket
supports.
Besides that the following methods and events are also available on JsonSocket
instances.
JsonSocket.sendSingleMessage(port, host, message, callback)
Sends a single message anc close the connection instantly.
Arguments
- port - Port to send the message to.
- most - Host to send the message to.
- message - The message to send.
- callback(err) - Will be called when the message has been sent.
JsonSocket.sendSingleMessageAndReceive(port, host, message, callback)
Sends a single message to host
:port
, waits for a response message, and closes the connection right after.
As soon as the response message is received the callback
function is invoked (if given) with the response message
as the second argument.
Arguments
- port - Port to send the message to.
- most - Host to send the message to.
- message - The message to send.
- callback(err, message) - Will be called when the response message has been received. The response message is given as the second argument.
socket.sendMessage(message, callback)
Sends a JSON a message over the socket.
Arguments
- message - The message to send.
- callback(err) - Will be called after the message has been sent.
socket.sendEndMessage(message, callback)
Same as socket.sendMessage
, except that the socket is closed right after the message has been sent using
net.end()
.
No more messages can be sent from either the server or client through this socket.
socket.sendError(err, callback)
Convenience method for sending an error as a message.
Arguments
- err - An Error object that should be formatted as a message.
- callback(err) - Will be called after the message has been sent.
Example
socket.sendError(new Error('Something went wrong!');
Will send a message of this JSON format:
{
"success": false,
"error": "Something went wrong"
}
socket.sendEndError(err, callback)
Same as socket.sendError
, except that the socket is closed right after the message has been sent using
net.end()
.
No more messages can be sent from either the server or client through this socket.
socket.isClosed()
Returns true if either the server or the client has closed the connection. Returns false otherwise.
Event: 'message'
- message - the message received from the other side.
Emitted when a complete message has been received.
How the protocol works
The JsonSocket
protocol works by JSON.stringify
'ing the message and prefixing it with a content length and a content length delimiter (#).
Example:
socket.sendMessage({
type: "ping"
});
Will send a message that looks like this:
15#{"type":"ping"}
This mechanism ensures that messages that are chunked will be parsed correctly.
##Todo
socket.request()
method, and request
event. Makes it easier to send multiple requests with callbacks.