Skip to main content

Socket.IO P2P

· 4 min read
Tom Cartwright

Today were very happy to introduce Socket.IO P2P, the easiest way to establish a bidirectional events channel between two peers with a server fallback to provide maximum reliability.

Lets look at the API and build a little chat application. Or check out the repository directly!

Socket.IO P2P provides an easy and reliable way to setup a WebRTC connection between peers and communicate using the socket.io-protocol.

Socket.IO is used to transport signaling data and as a fallback for clients where the WebRTC PeerConnection is not supported. Adding a simple piece of middleware to your socket.io setup enables this – no need to hand roll your own signaling exchange or set up, deploy and scale new servers.

Usage#

It only takes a few lines of code to set up the server and client.

Server:

var io = require('socket.io')(server);var p2p = require('socket.io-p2p-server').Server;io.use(p2p);

Client:

var P2P = require('socket.io-p2p');var io = require('socket.io-client');var socket = io();var p2p = new P2P(socket);p2p.on('peer-msg', function (data) {  console.log('From a peer %s', data);});

There are various options for the advanced user. Once signaling data has been exchanged an upgrade event is triggered and an optional callback is called.

var opts = { numClients: 10 }; // connect up to 10 clients at a timevar p2p = new P2P(socket, opts, function(){  console.log('We all speak WebRTC now');});

The Chat example#

We will build a simple chat application, as our tradition dictates, but with P2P capabilities! In this application:

  • Clients can send text messages to each other. Messages display in a timeline
  • Clients connect to each other over socket.io and initially send messages via the server
  • Clients can choose to go private – switching the transport to WebRTC
  • All clients connected to the server can connect via WebRTC up to a maximum of 10 clients

All code from this example is included in the main repository.

We first setup the client with autoUpgrade set to false so that clients can upgrade the connection themselves. Set numClients to 10 to allow up to 10 clients to connect with each other.

var opts = {autoUpgrade: false, numClients: 10};var p2psocket = new P2P(socket, opts)

Setup the event listeners:

p2psocket.on('peer-msg', function(data) {  // append message to list});
p2psocket.on('go-private', function () {  p2psocket.upgrade(); // upgrade to peerConnection});

In this example, we want any clients connecting to the server to exchange signaling data with each other. We can use the server component as a simple middleware. Clients will connect on the root namespace.

If we wanted clients to exchange signalling data in rooms, rather than on a whole namespace, we could use the server module upon connection like this.

var server = require('http').createServer();var p2pserver = require('socket.io-p2p-server').Servervar io = require('socket.io')(server);server.listen(3030)io.use(p2pserver);

We then setup listeners to pass messages between clients and to broadcast the go-private event.

io.on('connection', function(socket) {  socket.on('peer-msg', function(data) {    console.log('Message from peer: %s', data);    socket.broadcast.emit('peer-msg', data);  })
  socket.on('go-private', function(data) {    socket.broadcast.emit('go-private', data);  });});

Thats all you need: add a little markup we are off! Heres the demo application in action:

P2PChatExampleRedo2

Thanks to Guillermo Rauch (@rauchg) for the advice, testing and patience, Harrison Harnisch (@hharnisc) for bug fixes and to Feross Aboukhadijeh (@feross) for providing the underlying WebRTC abstraction simple-peer.

Pull requests, issues, comments and general rantings are all welcome over at the GitHub repo.