Run Multiple WebSocket Services On Same Port


Read {count} times since 2020

Are you as crazy as me when developing WebSocket applications ? It’s so awesome to work with WebSockets that will blow up your mind and irritate you at the same time.

WebSockets can be used for any real time applications such as :

  • Games
  • Chat
  • News
  • File Transfer

And because it’s impact is so vast, we can develop as many applications as we want. But, a problem arises for freebies like me and you.

Problem

Running multiple WebSocket servers for multiple apps requires you to run a listening node on different ports. But, on some hosting servers, this isn’t possible.

In case of OpenShift, this is impossible as there’s only one port in the app where you listen for incoming data ie 8080. See Port Binding On Openshift.

In this scenario, your only solution is to listen on a single port and send out data according to the service the client requested.

Francium DiffSocket

And for this purpose, I developed a small Composer package called Francium DiffSocket, an abbreviation for :

Francium Different Sockets

What it does is, allow you to add your own custom services and serve it through a single port. This means you can host your Online game serverChat server etc. on a single port.

Usage

Instructions on how to use it is in the README file of the project.

Demo

All of the WebSocket demos that I have created uses Francium DiffSocket. List :

Example

Let us make three different services :

  • A service that responds “hello” to incoming messages
  • A service that responds the incoming message itself (mimic)
  • A service that responds “hey, how are you ?” when “hi” is sent (bot)

We make three separate class files for the three services. These are stored in a folder called “services”.

Hello Service

Location – services/Hello.php

namespace Fr\DiffSocket\Service;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Hello implements MessageComponentInterface {
  public function onOpen(ConnectionInterface $conn){
    echo "New Connection - " . $conn->resourceId;
  }

  public function onClose(ConnectionInterface $conn){}
  public function onError(ConnectionInterface $conn,\Exception $error){}

  public function onMessage(ConnectionInterface $conn, $message){
    $conn->send("Hello");
  }
}

The API used to build the service is Ratchet as mentioned in the README file.

Mimic Service

Location – services/Mimic.php

namespace Fr\DiffSocket\Service;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Mimic implements MessageComponentInterface {
  public function onOpen(ConnectionInterface $conn){
    echo "New Connection - " . $conn->resourceId;
  }

  public function onClose(ConnectionInterface $conn){}
  public function onError(ConnectionInterface $conn,\Exception $error){}

  public function onMessage(ConnectionInterface $conn, $message){
    $conn->send($message);
  }
}

Bot Service

Location – services/Bot.php

namespace Fr\DiffSocket\Service;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Bot implements MessageComponentInterface {
  public function onOpen(ConnectionInterface $conn){
    echo "New Connection - " . $conn->resourceId;
  }

  public function onClose(ConnectionInterface $conn){}
  public function onError(ConnectionInterface $conn, \Exception $error){}

  public function onMessage(ConnectionInterface $conn, $message){
    if($message === "hi")
      $conn->send("hey, how are you ?");
  }
}

Okay, all of the services are made.

Run The Server

Now, we must make the code to integrate the services into Francium DiffSocket and then run the server.

require_once "vendor/autoload.php";
$DS = new \Fr\DiffSocket(array(
  "server" => array(
    "host" => "127.0.0.1",
    "port" => "8000"
  ),
  "service" => array(
    "hello" => __DIR__ . "/services/Hello.php",
    "mimic" => __DIR__ . "/services/Mimic.php",
    "bot" => __DIR__ . "/services/Bot.php"
  )
));

You can add more services by calling the addService() method too :

$DS->addService("service-name", "path/to/class.php");

Now, we can run the server :

$DS->run();

That’s it ! When the server is started, this message will be printed out :

Server started on 127.0.0.1:8000

You can connect to the different services in JavaScript like so :

var hello = new WebSocket("ws://localhost:8000/?service=hello");
hello.send("nothing"); // Server will respond "Hello"

var mimic = new WebSocket("ws://localhost:8000/?service=mimic");
mimic.send("Hola!"); // Server will respond "Hola!"

var bot = new WebSocket("ws://localhost:8000/?service=bot");
bot.send("hi"); // Server will respond "hey, how are you ?"

Use and hack the project all you want. It is licensed under the “Apache License”.