Creating an Internal WAMP (Web Application Messaging Protocol) Client for Thruway

The internal client in Thruway was built to allow an in-process client that would be able to inspect the Thruway server at run-time. The feature turned into the ManagerClient.

The internal client should really only be used for router extensions or possibly for prototyping or debugging. It is not a good idea to use the internal client feature for production application clients. (Blocking, Compatibility with other WAMP elements, etc.)

The InternalClientTransport can also be used to build a simple WAMP (Web Application Messaging Protocol) client that will always be running inside your server process.

If you are looking for an article on how to build a regular WAMP client in PHP (which is probably what you really want to do) – go here.

This post will show you how to create an internal client that will provide an RPC that queries the php version. (You could just as easily use this to do a number of simple things inside the server – check memory, load averages, etc.)

If you do decide to use the internal client in your server, you should keep in mind that Thruway is single-threaded. If you do anything that takes time, everything else must wait (network I/O, file I/O, etc. would be problematic, unless you are going to use react for asynchronous I/O).

First of all, you should setup your project. Follow the steps in the readme up until the point of starting the example server.

Copy the example SimpleWsServer.php (in vendor/voryx/thruway/Examples/SimpleWsSRouter.php) to root of your new project.

Change the autoload statement at the top as we have moved this file.

It should read:

require __DIR__ . '/vendor/autoload.php';

Try this and make sure that everything is working.

php SimpleWsRouter.php

You should have a running server now. If you want to try it, you should be able to open another shell and run the SimpleClient script in vendor/voryx/thruway/Examples.

Now, we are going to create a new class that will be our internal client. Just create a new file called InternalClient.php.

Add the open php tag and autoload statement to the top.

<?php
require __DIR__ . '/vendor/autoload.php';

We are going to subclass Thruway\Client.

Add:

class InternalClient extends Thruway\Peer\Client {

}

We override the constructor. We don’t need to, but I think it is best to do it so that if you do in the future, you remember to call the parent constructor, which is needed to set the realm information.

We are also going to setup a hook for the session start. This event will let us know we are good to use the session, whether we want to publish something or register an RPC call.

function __construct()
{
    parent::__construct("realm1");

}

public function onSessionStart($session, $transport) {
    // TODO: now that the session has started, setup the stuff
}

There is one last thing we need to do, and then our skeleton internal client will be complete. We must override start because we are not your typical client. We have no real transport and we do not start a loop (all calls from the server will be direct calls – no I/O). Overriding start is no longer necessary as the InternalClientTransportProvider will pass false to start telling it not to start the loop.

If we did want to use a react loop for something, the best thing to do would be to create a loop prior to instantiation and send it into the constructor, saving it in a property for later use. (Such as timers, subprocesses, or network I/O)

Now that our InternalClient class skeleton is complete, we will hook it into the SimpleWsServer.php that we copied. To do this, we are going to add an InternalClientTransportProvider that will take an instance of a Client as an argument.

First add a require statement for our class file underneath the autoloader.

require 'InternalClient.php';

Right after the addTransportProvider call that is made for the Ratchet provider, add the following lines.

$router->addInternalClient(new InternalClient());

Everything should be wired up now and ready to go. It doesn’t do anything right now, so we should add something to it to know that it is working.

Add the following to the body of the onSessionStart method:

echo "--------------- Hello from InternalClient ------------";

Now, fire up the server script again.

php SimpleWsRouter.php

You should see the hello message that we echoed. Now we can add the php version RPC. We are going to create a method on our client that will handle this call.

Add this method to the class:

function getPhpVersion() {
    return array(phpversion());
}

All RPC calls must return arrays.

Add this in place of the hello message.

$this->getCallee()->register($this->session, 'com.example.getphpversion', array($this, 'getPhpVersion'));

Now you should be ready to run your InternalClient with an RPC call.

Start your server back up. (Restart if you never killed it)

I have created a plunker here so you can test your RPC call.

Leave a Reply