Ruppell's Sockets

This add-on is operated by Ruppell's

TCP sockets for your apps

Ruppell's Sockets

Last Updated: 07 May 2015

The Ruppell's Sockets add-on is currently in beta.

Table of Contents

Ruppell’s Sockets is an add-on for routing TCP Sockets to your app’s dynos.

TCP Sockets are a lower level protocol than HTTP and allow for the custom protocols often seen in client side applications like chat clients, email clients and multi-player games.

Ruppell’s Sockets allow non-HTTP applications that require TCP sockets like IRC, Jabber, game servers, or your own custom TCP server to run on Heroku.

All TCP socket libraries work with Ruppell’s Sockets. You will find mature socket libraries and frameworks in virtually every language so getting started is simple.

TCP sockets aren’t websockets. Websockets are often used by web browsers to enable bi-directional communication in a web page. TCP sockets are often used directly by non-web browser applications like email, chat or IRC clients or multi-player games. A good example of a protocol you’d want to talk over TCP instead of websockets is XMPP.

Provisioning the add-on

Ruppell’s Sockets can be attached to a Heroku application via the CLI:

A list of all plans available can be found here.

$ heroku addons:create ruppells-sockets
-----> Adding ruppells-sockets to sharp-mountain-4005... done, v18 (free)

Once Ruppell’s Sockets has been added a RUPPELLS_SOCKETS_FRONTEND_URI setting will be available in the app configuration and will contain the frontend URI for your clients to connect to. Connections to this URI from the internet will be load balanced to the TCP ports your app’s dynos are listening on. This setting can be confirmed using the heroku config:get command.

$ heroku config:get RUPPELLS_SOCKETS_FRONTEND_URI
tcp://4950.381b424d-12fa-4fad-b464-9013a482ca7f.sockets.ruppells.io:4950

A RUPPELLS_SOCKETS_TUNNEL_URI setting is also added. This won’t be used directly by your app and can be ignored.

It is used internally by the helper script introduced in the next section and contains the tunnel URI used to connect the app’s local TCP socket to the Ruppell’s Sockets router.

Connecting your app to Ruppell’s Sockets

The supported method of connecting an app to a Ruppell’s Sockets tunnel is the Ruppell’s Sockets helper script. This should be added as a git submodule to your app by running the following command in your app’s directory:

$ git submodule add https://bitbucket.org/ruppells/sockets-connect.git lib/sockets-connect
Cloning into 'lib/sockets-connect'...

If using a “web” dyno as a socket endpoint remember to to also listen for HTTP connections on the PORT setting.

Heroku health checks HTTP on web dynos and marks them as crashed if they don’t respond. See Declaring process types for more information.

Modify the app’s Procfile to run the app with rs-conn from the submodule directory.

web: ./lib/sockets-connect/rs-conn ./web_api.js
socket: ./lib/sockets-connect/rs-conn ./tcp_listener.js

The rs-conn helper script injects a RUPPELLS_SOCKETS_LOCAL_PORT setting into the app configuration. This is the port for the app to listen for TCP connections on.

Connecting clients to your app

Your clients must connect to the TCP URI specified by the RUPPELLS_SOCKETS_FRONTEND_URI setting.

The recommended ways of connecting clients to the frontend URI are:

  • Bootstrap the clients with the TCP frontend URI over a traditional Heroku HTTP endpoint.
  • Set up a DNS CNAME on your own domain to issue to clients.

While it is safe to use a CNAME for the host name, the port is used to route traffic to your app and must remain the same.

Using with Node.js

Node.js is an event driven non-blocking framework that makes it simple to write HTTP and TCP applications. If you’re new to Node.js start with Getting started with NodeJS.

net = require('net');
var ruppells_sockets_local_port = process.env.RUPPELLS_SOCKETS_LOCAL_PORT;
net.createServer(socketHandler).listen(ruppells_sockets_local_port);

A Node.js example TCP/HTTP chat app can be downloaded from https://bitbucket.org/ruppells/nodejs-tcp-ws-chat-demo.

Using with other languages and frameworks

Virtually every server side language and framework has socket handler. If your favourite is missing please use the feedback link below to tell us!

  • Python
  • Ruby
    • eventmachine
    • Sockets are generally considered low level, most use them indirectly through a framework
  • Java
    • Sockets programming in Java: A tutorial is a good starting point for getting started with sockets in Java
    • NIO is a non-blocking API that can be used to build high concurrency socket servers in Java and other JVM languages

App Status Codes

Ruppell’s Sockets status and errors are logged to your Heroku logs. Below is a description of logs you may see.

Status codes

201 - app connected

A dyno has authenticated and connected to Ruppell’s Sockets

202 - port tunnel connected

A dyno has connected to a tunnelled external port

203 - port tunnel disconnected

A dyno has disconnected from a tunnelled external port

204 - app disconnected

A dyno has disconnected from Ruppell’s Sockets

Error codes

401 - bad port

The frontend port requested is not allocated to this app

Troubleshooting

Why won’t my TCP clients connect after a period of time?

Is your TCP socket code sharing your web dyno?

If you are only running one web dyno it will idle. If this happens Ruppell’s Sockets disconnect all currently connected clients until an http request wakes your web dyno again.

If you move your sockets to a non-web dyno or scale your web dyno to 2 or more they won’t sleep and your clients connections will be more reliable.

Why do my TCP clients disconnect periodically?

Heroky dynos are cycled at least once a day. This disconnects any clients currently connected to that dyno.

That may sound far from ideal but this cycling keeps Heroku stable and is only one of many things that WILL interupt TCP connections on the internet.

A reliable TCP client should handle dropped connections gracefully, usually by reconnecting to the server. The mechanism of reconnection varies deplending on your use case but the internet is full of good advice on how to achieve this.

Why is my web dyno marked as crashed shortly after startup

Are you accepting HTTP on the port defined in the PORT config setting?

Heroku health checks HTTP on web dynos and marks them as crashed if they don’t respond.

I found a bug in the rs-conn helper. Will you fix it?

Of course! Aside from the normal Heroku support channels issues can be submitted to the rs-conn repo here.

Pull requests are also welcome if you know how to fix it.

Removing Ruppell’s Sockets

Ruppell’s Sockets can be removed via the CLI.

This will destroy all associated data and cannot be undone!

$ heroku addons:destroy ruppells-sockets
-----> Removing ruppells-sockets from sharp-mountain-4005... done, v20 (free)

Support

All Ruppell’s Sockets support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome at heroku-sockets-support@ruppells.io.