EzDev.org

ratchet

Build mobile apps with simple HTML, CSS, and JavaScript components. Ratchet ratchet: build mobile apps with simple html, css, and js components.


Send user ID from browser to websocket server while opening connection

Before asking this question, I did my best by reading severel questions on SO (tagged Ratchet and dealing with similar issues but to no avail. I even asked a question which received no attention and I therefore deleted it to write another one (that hopefully is more clear).

My final goal is to build a one-to-one private chat application using Ratchet. Everything is working fine except that I can't send message to a specific user.

Every logged in user connects to the websocket server while accessing secured area of website:

$(document).ready(function() { 

    var conn = new WebSocket('ws://localhost:8080');
        conn.onopen = function(e) {
            console.log("Connection established!");

            // Here I need to send the logged in user_id to websocket server
            // and get it in onOpen method so that I can index my array 
            // of connections with user_id instead of
            //$connection->ResourceId, I explain more above

        };

        conn.onmessage = function(e) {
            console.log(e.data);
        };

});

When a user writes a message in the chat box, the message is sent via AJAX to web server then pushed to Websocket using ZeroMQ. In the controller:

// Persistence of Message(message_id, sender_id, receiver_id, message_text)
                .....

                $context = new \ZMQContext();
                $socket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher');
                $socket->connect("tcp://localhost:5555");

                $pushData = array(
                       'receiver_id' => $receiver_id,
                       'sender_id'  => $user->getId(),
                       'message'  => $message->getMessageText(),
                    );
                $socket->send(json_encode($pushData));

So at the end, my websocket server is able to know which is the id of receiver using the JSON. But how will he know which is the connection of that user? In other words, I need to store websocket connections in an array that is indexed by the user id.

<?php
namespace RealTime;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Wamp\WampServerInterface;

class Pusher implements WampServerInterface, MessageComponentInterface{

    private $clients;

    public function onOpen(ConnectionInterface $conn) {

        $this->clients[$conn->resourceId] = $conn;
        // I need here to get the user_id received from browser while opening connection
    }

    public function onMessageEntry($entry) {
        $entryData = json_decode($entry, true);

        //This is not what I need (It sends to all users in array)
        foreach ($this->clients as $key => $client) {

        $client->send($entryData['message']); 
        }
    }
    public function onMessage(ConnectionInterface $from, $msg) {
        echo $msg; 
    }
}

And the websocket server:

  <?php
        require dirname(__DIR__) . '/vendor/autoload.php';
        use RealTime\Pusher;

        $loop   = React\EventLoop\Factory::create();
        $pusher = new Pusher;

        $context = new React\ZMQ\Context($loop);
        $pull = $context->getSocket(ZMQ::SOCKET_PULL);
        $pull->bind('tcp://127.0.0.1:5555'); 
        $pull->on('message', array($pusher, 'onMessageEntry'));


        $webSock = new React\Socket\Server($loop);
        $webSock->listen(8080, '0.0.0.0'); 
        $webServer = new Ratchet\Server\IoServer(
            new Ratchet\Http\HttpServer(
                new Ratchet\WebSocket\WsServer(
                    new Ratchet\Wamp\WampServer(
                        $pusher
                    )
                )
            ),
            $webSock
        );
        $loop->run();

        ?>

Questions:

  1. How to send the logged in user_id from client side while opening connection.I need to have the value in websocket server so that I can index my array of clients with it ($client[user_id]=$conn instead of $client[recourceId]=$conn). I tried the javascript function send but I don't know where to receive the sent data (even onMessage is not printing anything).

  2. Why the onMessage method is not executing even MessageComponentInterface implemented (Is it because I have onMessageEntry method + $pull->on('message', array($pusher, 'onMessageEntry')); line of code?

Thank you.


Source: (StackOverflow)

Programmatically load a url using Ratchet push.js

The Ratchet single-page application framework uses push.js to load new pages into view. For example:

<a rel='nofollow' href="link.html">link<a>

This will use push to replace everything in the .content div with the .content of link.html. It will also update .bar-title and .bar-tab if you have them on both pages.

I would like to use the same mechanism with a Javascript function call. Before I start patching Ratchet, is there an elegant way to do that?

Thanks!


Source: (StackOverflow)

Ratchet Session Data Syncronisation using memcache

I created a Ratchet Web Socket Server and tried to use SESSIONS.

In my php file on the HTTP-Webserver (Port 80) I set the session-data like this

use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler;

$memcache = new Memcache;
$memcache->connect('localhost', 11211);

$storage = new NativeSessionStorage(array(), new MemcacheSessionHandler($memcache));
$session = new Session($storage);
$session->start();

$session->set('uname', $uname);

and connected to the Ratchet Websocket Server with Javascript

var RatchetClient = {

    url: "ws://192.168.1.80:7070",

    ws: null,

    init: function() {

        var root = this;
        this.ws = new WebSocket(RatchetClient.url);

        this.ws.onopen = function(e) {
            console.log("Connection established!");
            root.onOpen();
        };

        this.ws.onmessage = function(evt) {
            console.log("Message Received : " + evt.data);
            var obj = JSON.parse(evt.data);
            root.onMessage(obj);
        };

        this.ws.onclose = function(CloseEvent) {
        };

        this.ws.onerror = function() {
        };
    },

    onMessage : function(obj) {    
    },

    onOpen : function() {        
    }
};

The Server script works like descripted here: http://socketo.me/docs/sessions

If the client sends a message I fetch the session-data

$memcache = new Memcache;
$memcache->connect('localhost', 11211);

$session = new SessionProvider(
    new MyServer()
  , new Handler\MemcacheSessionHandler($memcache)
);


$server = IoServer::factory(
    new HttpServer(
        new WsServer($session)
    )
  , 7070
);

$server->run();



class MyServer implements MessageComponentInterface {

    public function onMessage(ConnectionInterface $conn, $msg) {

        $name = $conn->Session->get("uname");

    }
}

It works. If i set the session-data before connecting to the websocket then the uname is fechable inside my socket server script.

Whenever I change the session-data via ajax or from another browser window then the session-data of my running client will not been syncronized.

That means if i change the uname or destroy the session the socket server doesn't recognize this. It seems to be the case that Ratchet reads the session-data once on connect and after that the session object is independent.

Can you confirm that behaviour? Or am I doing something wrong. I thought the goal of using memcache is to be able to access the same session-data from different connected clients.

If I do a reconnect to the websocket after changing the session-data then the data has been updated.


Source: (StackOverflow)

Node.js with Laravel 4.2

I currently working on php project - Laravel 4.2 framework. I need to use node.js. Need to real time update count of users that registered, on dashbord.

I tried with Ratchet , but I'm not clear following file path that we must edit.

  • /src/MyApp/Chat.php
  • /bin/chat-server.php

Does someone have experience working with node.js on Laravel? Please help me.


Source: (StackOverflow)

Using PHP Pthreads with Ratchet Websocket

I am making an html5 game www.titansoftime.com

I am using ratchet as a php websocket server solution. It works great! http://socketo.me/docs/push

I have done several standalone test using the php pthreads extension and have seen some very exciting results. It truly works and works well.. as long as websockets aren't in the mix.

Pthreads give php multithreading capabilities (it really does work and it's amazing). http://php.net/manual/en/book.pthreads.php

This is what I do:

/src/server.php This is the file that launches the daemon.

    <?php
    session_start();

    use Ratchet\Server\IoServer;
    use Ratchet\WebSocket\WsServer;
    use MyApp\Pusher;

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

    require_once __DIR__ . '/../mysql.cls.php';
    require_once __DIR__ . '/../game.cls.php';
    require_once __DIR__ . '/../model.cls.php';

    $mysql = new mysql;
    $game  = new game;

    $loop   = React\EventLoop\Factory::create();
    $pusher = new MyApp\Pusher();

    $loop->addPeriodicTimer(0.50, function() use($pusher){
        $pusher->load();
    });

    $webSock = new React\Socket\Server($loop);

    if ($loop instanceof \React\EventLoop\LibEventLoop) {
        echo "\n HAS LibEvent";
    }

    $webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
    $webServer = new Ratchet\Server\IoServer(
            new Ratchet\Http\HttpServer(
                    new Ratchet\WebSocket\WsServer($pusher)
            ),
            $webSock
    );

    $loop->run();

This all works fine.

/src/MyApp/Pusher.php This class pushes data to all connected users.

<?php
namespace MyApp;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;

class AsyncThread extends \Thread{

    public $client;

    public function __construct($client){
        $this->client = $client;
    }

    public function run(){

        // do work on $this->client
        $user = mysql::assoc('SELECT * from users WHERE connection_id = "'.$this->client->resourceId.'"');
        // etc..
        $this->client->send(json_encode(array('foo'=>'bar')));

    }

}

class Pusher implements MessageComponentInterface{

    public static $clients = array();

    #load
    public static function load(){

        $client_count = count(self::$clients);

        echo "\n\n\n".'Serving to '.$client_count.' clients. '.time();

        $start = $istart = microtime(true);

        if( !count(self::$clients) ){
            if( !mysql_ping() ){
                $game->connect();
            }
        }

        $threads = array();
        foreach( self::$clients as $key => $client ){       

            // HANDLE CLIENT

            // This works just fine, the only problem is that if I have lets say 50 simultaneous users, the people near the end of the clients array will have to wait till the other users have been processed. This is not desirable
            $client->send(json_encode('foo'=>'bar'));

           // So I tried this:
           $threads[$key] = new AsyncThread($client);
           $threads[$key]->start();

           // At this point the AsyncThread class will throw a fatal error complaining about not being able to serialize a closure. 
          // If I dont set "$this->data = $client;" in the thread constructor no error appears but now I cant use the data.

           // Also regardless of whether or not I bind the data in the AsyncThread constructor,
           // the connection disappears if I call "new AsyncThread($client)". I cannot explain this behavior.

        }

    }

    public function onMessage(ConnectionInterface $from, $msg) {
        global $game;
        if( $msg ){
            $data = json_decode($msg);
            if( $data ){    

                switch( $data->task ){

                    #connect
                    case 'connect':
                        echo "\n".'New connection! ('.$from->resourceId.') '.$from->remoteAddress;
                        self::$clients[] = $from;
                        break;

                    default:
                        self::closeConnection($from);
                        echo "\nNO TASK CLOSING";
                        break;

                }
            }else{
                echo "\n NO DATA";
                self::closeConnection($from);
            }
        }else{
            echo "\n NO MSG";
            self::closeConnection($from);
        }
    }

    public function closeConnection($conn){
        global $game;
        if( $conn ){
            if( $conn->resourceId ){
                $connid = $conn->resourceId;
                $conn->close(); 
                $new = array();
                foreach( self::$clients as $client ){
                    if( $client->resourceId != $connid ){
                        $new[] = $client;
                    }
                }
                self::$clients = $new;
                $game->query('UPDATE users set connection_id = 0 WHERE connection_id = "'.intval($connid).'" LIMIT 1');
                echo "\n".'Connection '.$connid.' has disconnected';
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        echo "\nCLIENT DROPPED";
        self::closeConnection($conn);
    }

    public function onOpen(ConnectionInterface $conn) {
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "\nCLIENT ERRORED";
        self::closeConnection($conn);
    }
    public function onSubscribe(ConnectionInterface $conn, $topic) {
    }
    public function onUnSubscribe(ConnectionInterface $conn, $topic) {
    }
    public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
    }
    public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
    }

}

This all works fine as long as I don't create a thread inside the event loop.

Am I going about this the wrong way or is php multithreading and websockets incompatible?


Source: (StackOverflow)

Uncaugth reference error custom event not defind in the file ratchet

Hai i am new in phonegap and ratchet framework.I am trying to load external script with push.js. Here is my js file contents

function init(){
    document.addEventListener('deviceready', onDeviceReady, false);

    function onDeviceReady(){

        alert("device ready for use");
        }
       var checkPage = function(){

        alert("push");
        var scriptName; 
        var scriptsList = document.querySelectorAll('script.js-custom');  // Add a "js-custom" class to your script tag
        for (var i = 0; i<scriptsList.length;i++) {

            // Handle scripts in separate files by assigning the script file name to its id.
            // We save it in a variable because the ".done" callback is asynchronous.
            scriptName = scriptsList[i].id;  // IMPORTANT: Only one loadable script per page!
            $.getScript("js/" + scriptName)
              .done(function (script, textStatus) {
                  eval(script);
                  alert("ok");
              })
              .fail(function(){
                  alert("error");
              });

        }


    };   

    window.addEventListener('push', checkPage);

    } 

Here is my html file

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">  
    <title>Ratchet template page</title>

    <!-- Sets initial viewport load and disables zooming  -->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">

    <!-- Makes your prototype chrome-less once bookmarked to your phone's home screen -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">

    <!-- Include the compiled Ratchet CSS -->
    <link rel='nofollow' href="css/ratchet.min.css" rel="stylesheet">

    <!-- Include the compiled Ratchet JS -->
    <script src="js/ratchet.min.js"></script> 
    <script src="js/jquery.js"></script>
     <script src="cordova.js"></script>

  </head>
  <body onload="init()">  

    <!-- Make sure all your bars are the first things in your <body> -->
    <header class="bar bar-nav">
      <h1 class="title">Ratchet</h1>
    </header>

    <!-- Wrap all non-bar HTML in the .content div (this is actually what scrolls) -->
    <div class="content">

      <div class="card">
        <ul class="table-view">
          <li class="table-view-cell">

            <a class="push-right" rel='nofollow' href="two.html">
              <strong>Another page</strong>
            </a>
          </li>  
          <li class="table-view-cell"> 
            <a class="push-right" rel='nofollow' href="https://github.com/twbs/ratchet/">
              <strong>Ratchet on Github</strong>
            </a>

      </div>
    </div>

Here is my two.html file

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Notes</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">

    <!-- Roboto
    <link rel="stylesheet" rel='nofollow' href="//fonts.googleapis.com/css?family=Roboto:400,500,700"> -->

    <link rel="stylesheet" rel='nofollow' href="ratchet.min.css">
    <script src="ratchet.min.js"></script>
  </head>
  <body>
      <header class="bar bar-nav">
  <h1 class="title">Two</h1>
    </header>
  </body>
  <div class="content">
  <script src="js/sample.js" class="js-custom" id="sample.js"></script>
  </div>
</html>

But i run the project i get

Uncaught ReferenceError: CustomEvent is not defined at file:///android_asset/www/js/ratchet.min.js:10

please help me.


Source: (StackOverflow)

PHP WebSockets with Ratchet - example doesn't work

Here's some background first.

1) My aim is to use Ratchet WebSockets to create two-way client-server communication.

2) I have installed ratchet and accompanying software, as described here.

3) I have successfully created a Hello World application as described here.

4) Now I am trying to create Push functionality using this tutorial. I have copied the code, modifying it slightly (modifications noted in code comments below), installed the ZMQ library (latest version, added it to php.ini, show up in php -m - in short, it's installed correctly). But the WebSockets don't work.

I will give my testing process with real live links to my domain below, so you can check it yourself.

1) My push server is exactly the same as the one in their tutorial, with the IP changed to my server's IP. I run this through SSH and it seems to connect correctly.

2) My Pusher class is in the MyApp namespace, same code and same relative location as in their tutorial.

3) My post.php is slightly modified because there's no need to bother with MySQL queries:

$entryData = array(        //hard-coded content of $entryData for simplicity
    'cat'     => "macka"
  , 'title'   => "naslov"
  , 'article' => "tekst"
  , 'when'    => time()
);

// This is our new stuff
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://light-speed-games.com:5555");       //my domain, still using port 5555 as in their example

$socket->send(json_encode($entryData));

This file is located here.

4) My client.php is the same as theirs, except I had to add a little fix for IE to work with when.js. My problem is browser-independent and the same as it was before the fix was added.

<script>
    window.define = function(factory) {    //my addition
        try{ delete window.define; } catch(e){ window.define = void 0; } // IE
        window.when = factory();
    };
    window.define.amd = {};
</script>
<script src="/apps/scripts/when.js"></script> 
<script src="http://autobahn.s3.amazonaws.com/js/autobahn.min.js"></script>
<script>
    var conn = new ab.Session(
        'ws://light-speed-games.com:8080' // The host (our Ratchet WebSocket server) to connect to
      , function() {            // Once the connection has been established
            conn.subscribe('kittensCategory', function(topic, data) {
                // This is where you would add the new article to the DOM (beyond the scope of this tutorial)
                console.log('New article published to category "' + topic + '" : ' + data.title);
            });
        }
      , function() {            // When the connection is closed
            console.warn('WebSocket connection closed');
        }
      , {                       // Additional parameters, we're ignoring the WAMP sub-protocol for older browsers
            'skipSubprotocolCheck': true
        }
    );
</script>

This file is located here.

In theory, what should happen is this (for example): I open client.php in Chrome with console switched on; then I open post.php in Firefox; Chrome's console should show the message 'New article published...' etc (from the conn.subscribe function in client.php). However, when I do this, nothing happens. The connection remains open (doesn't show the 'connection closed' error until I switch off push-server.php through SSH). The console remains empty.

I think that's all the relevant info from the last couple of days, a large portion of which I've spent on trying to figure this out. However, I've been unable to even make sure if the problem is with the code or with some server configuration setting I may be unaware of. So, I come to you hoping someone will point me in the right direction.

IMPORTANT EDIT:

I'm pretty sure the problem is with the Autobahn.js method conn.subscribe not working properly. The connection is being established. When I change the code to:

function() {            // Once the connection has been established
            console.log('Connection established');
            conn.subscribe('kittensCategory', function(topic, data) {
                // This is where you would add the new article to the DOM (beyond the scope of this tutorial)
                console.log('New article published to category "' + topic + '" : ' + data.title);
            });
        }

Then Connection established is shown in the console correctly. So I believe we need to troubleshoot the subscribe method. If someone can explain to me how it works, and what exactly "topic" and "data" are supposed to be, ti would be of great help. The Autobahn documentation uses a URL as an argument for this method (see here).


Source: (StackOverflow)

Failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

I try to connect with socket to my server. My server is running server socket with Rachet on port 8080. I try to run this code:

<script>   

    try{
    conn = new WebSocket('wss://localhost:8080');


conn.onclose = function (e)
{
        //checkUser();
}

conn.onopen = function(e) 
{
    console.log("test");
};

    }catch (error)
{
    console.log(error);
}

  </script>

But I get this error:

WebSocket connection to 'wss://localhost:8080/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

When I try to connect from my linux shell I get this:

root@(none):~# telnet localhost 8080
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Source: (StackOverflow)

Access extra parameters in Ratchet web socket requests

I've set up Ratchet for websockets in PHP . It is connecting fine from my javascript client using (ws://localhost:8080) and successfully send/receive messages. But I want to pass some params like (ws://localhost:8080?param1=value). I'm not able to figure out how can I access param1 in my PHP script.

If possible in MessageComponentInterface::onOpen(ConnectionInterface $conn) method.

Or better: Can I associate those params with ConnectionInterface $conn. So that I've them for further communication.

I've followed http://socketo.me/docs/hello-world.


Source: (StackOverflow)

how to get the connection object of a specific user?

I am working in a real time Symfony app using Ratchet library, in this app I need to send some data to a specific user so the logic solution was to use the SessionProvider that will attach a Symfony2 Session object to each incoming Connection object. As the documentation states I have setup a non-native session handler to store my sessions i.e. in a database via PDO. and that work fine for the moment but I need to get the Connection object of a specific user to send him some data so in other way I need to find the connection object that reference to this user and I can't find a way to do it ? her's my server code :

    $app=new AggregateApplication();
    $loop   = \React\EventLoop\Factory::create();
    $context = new \React\ZMQ\Context($loop);
    $pull = $context->getSocket(\ZMQ::SOCKET_PULL);
    $pull->bind('tcp://127.0.0.1:5555');
    $pull->on('message', array($app, 'onNotification'));
    $webSock = new \React\Socket\Server($loop);
    $webSock->listen(8080, '127.0.0.1');
    $handler = $this->getContainer()->get('session.handler');
    $server=new \Ratchet\Wamp\WampServer($app);
    $server = new SessionProvider($server, $handler);
    $webServer = new \Ratchet\Server\IoServer(new \Ratchet\WebSocket\WsServer($server),$webSock);
    $loop->run();

Source: (StackOverflow)

Ratchet / When.js: "Uncaught ReferenceError: module is not defined"

I'm trying to use ratchet for reflecting the changes made to my database realtime. I used the code of the pusher app (http://socketo.me/docs/push). But i am getting error in that.

The moment I open the client side page :

Uncaught ReferenceError: module is not defined                    when.js:900
(anonymous function)                                              when.js:900
(anonymous function)                                              when.js:15
(anonymous function)                                              when.js:900

After this I typed: conn.subscribe('topic'); //This subscribes the topic.

Now the moment I make changes to this topic, an error pops up where the changes are to be displayed.

Error 2 :

Uncaught TypeError: undefined is not a function         [VM] autobahn.min.js (124):66
(anonymous function)                                    [VM] autobahn.min.js (124):66
c._websocket.onmessage                                  [VM] autobahn.min.js (124):66

Any help ?


Source: (StackOverflow)

Ratchet / Websockets : How many clients subscribing to an object?

I would like to know how many clients are actually subscribing to a chatroom / conversation.

To be more precise, i just want to know if there is more than 1 client. (Chatroom are actually a private conversation between two users).

There is only one chatroom / private conversation at a time (per user).

class Chat implements WampServerInterface
{
    protected $conversationId;
    public function __construct(){
        $this->conversationId = null;
    }
    public function onSubscribe(ConnectionInterface $conn, $conversation_id){
        $this->conversationId = $conversation_id;
        echo "Client $conn->resourceId assigned to the conversation : $conversation_id\n";
    }
    public function onPublish(ConnectionInterface $conn, $conversation_id, $event, array $exclude, array $eligible){
        // How to get $nb_clients ?
        echo "$nb_clients User(s) in conversation";
        echo "Message sent to $conversation_id : $event";
        // ...
        $message = $event; 
        // Send data to conversation
        $this->conversationId->broadcast($message);
    }
}

So in the given code, how to get $nb_clients?


Update:

I guess I'm starting to see a solution.

Here my second attempt:

class Chat implements WampServerInterface
{
    protected $conversation  = array();
    public function onSubscribe(ConnectionInterface $conn, $conversation_id){
        $conversation_id = (string) $conversation_id;
        if(!array_key_exists($conversation_id, $this->conversation)){
            $this->conversation[$conversation_id] = 1;
        }
        else{
            $this->conversation[$conversation_id]++;
        }
        echo "{$this->conversation[$conversation_id]}\n";
        echo "Client $conn->resourceId assigned to the conversation : {$conversation_id}\n";
    }
    public function onUnSubscribe(ConnectionInterface $conn, $conversation_id){
        // Foreach conversations or given conversation remove one client
        $this->conversation[$conversation_id]--;
        echo "$this->conversation[$conversation_id]\n";
        echo "Client $conn->resourceId left the conversation : $conversation_id\n";
    }
    public function onOpen(ConnectionInterface $conn){
        echo "New connection! ({$conn->resourceId})\n";
    }
    public function onClose(ConnectionInterface $conn){
        $this->onUnsubscribe($conn, $this->conversation);
        echo "Connection closed!\n";
    }
    public function onCall(ConnectionInterface $conn, $id, $fn, array $params){
    }
    public function onPublish(ConnectionInterface $conn, $conversation_id, $event, array $exclude, array $eligible){
        $conversation_id = (string) $conversation_id;
        $nb_clients = $this->conversation[$conversation_id]
        echo "$nb_clients User(s) in conversation";
        echo "Message sent to $conversation_id : $event";
        // ...
        $message = $event; 
        // Send data to conversation
        $this->conversation[$conversation_id]->broadcast($message);
    }
    public function onError(ConnectionInterface $conn, \Exception $e){
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }
}

Any ideas if that would properly work? It actually seems to work but i'm still not sure if it is the best solution. I actually got inspired from Ratchet github.


Source: (StackOverflow)

Ratchet + nginx + SSL/secure websocket

I've been trying to run Ratchet.io over SSL (this problem: php ratchet websocket SSL connect?).

My webserver is running at myhost.mobi, and I have created a separate virtual host for websocket service "wws.myhost.mobi".

My web socket:

$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            new Ratchet\Wamp\WampServer(
                $pusher
            )
        )
    ),
    $webSock
);

My nginx config (I'm on nginx 1.5.8):

upstream websocketserver {
        server localhost:8080;
}

server {
    server_name wss.myapp.mobi;

    listen 443;
    ssl on;
    ssl_certificate /etc/ssl/myapp-mobi-ssl.crt;
    ssl_certificate_key /etc/ssl/myapp-mobi.key;

    access_log /var/log/wss-access-ssl.log;
    error_log /var/log/wss-error-ssl.log;
    location / {
                proxy_pass http://websocketserver;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto https;
                proxy_read_timeout 86400; # neccessary to avoid websocket timeout disconnect
                proxy_redirect off;
        }
}

My client-side script:

var conn = new ab.Session('wss://wss.myapp.mobi', function(o) {

    // ...

}, function() {
    console.warn('WebSocket connection closed');
}, {
    skipSubprotocolCheck: true
});

So, when I load the page in Firefox, I see an outgoing connection to wss://wss.myapp.mobi:8080/, which is hanging (the spinner) and never completes or dies. I do not see any trace of request arriving on the backend in the logs.

What am I missing there?

Thanks!

EDIT I have realized that I should be connecting to wss://wss.myapp.mobi, but now I am getting "101 Switching Protocols" status.

EDIT 2 Everything is working now with the config above. "101 Switching Protocols" status turns out to be a normal message. PROBLEM SOLVED!


Source: (StackOverflow)

looking up data in splobjectstorage

Greetings people of stackoverflow, for the last days I have been looking at websockets and a PHP library called Ratchet (which is ideal for writing websockets server applications in PHP). In the Ratchet official docs they recommend using SplObjectStorage (which I had never heard of) for managing client connections objects.

In most server applications you probably need to keep some data about each client (e.g. in my case where I'm experimenting with writing a simple messaging server, I need to keep data like the client's nickname and perhaps something more), so as I understand it, I can add the client object and an array with the clients data to the SplObjectStorage when a new connection is opened like here below.

public function onOpen(ConnectionInterface $conn) {
    //$this->clients is the SplObjectStorage object
    $this->clients[$conn] = array('id' => $conn->resourceId, 'nickname' => '');

}

However, I'm not sure what is the best way to get an object from the SplObjectStorage by a value in the data array (like by a users nickname), one way to do it would be like this:

//$this->clients is my SplObjectStorage object where I keep all incoming connections
foreach($this->clients as $client){ 
    $data = $this->clients->offsetGet($client);

    if($data['nickname'] == $NickNameIAmLookingFor){
        //Return the $client object or do something nice
    }
}

But I sense there is a better way of doing this, so any advices would be greatly appreciated.

Thanks in advance.


Source: (StackOverflow)

How to bind ZeroMQ socket with Ratchet web-socket library to make real time application for php application?

I am just a beginner in this whole area involving websocket, Ratchet and ZeroMQ.

To my basic understanding:

websocket is something that helps to create open connection between server and client.

Ratchet is a PHP based library which uses PHP's core Socket functions to create a PHP socket framework allowing us to ease in PHP socket programming.

ZeroMQ is a socket library that helps non-ratchet application to (other PHP script) send the data over Ratchet Socket and web-socket.

I am following the tutorial found in ratchet about 'hello world' and 'pusher' but both of them seems to be incomplete and only teaches how to work with console only. I have also found ratchet-example in github but it is not properly documented. I was looking for a complete example (with a dedicated html page and javascript)

Below is the code I am working on: This is one of the method of the controller which I am making a Ajax request for. This method will create a new post (lets say). I want to update the list of post dynamically in multiple client's browser by broadcasting/pushing with the help of ZeroMq.

A method in a controller:

public function create_new_post(){
    // ------
    // code to create a new post.
    // -------

    // After creating a post
    $response = [
        'new_post_title'    => $title,
        'post_id'           => $id
    ];

    $context = new ZMQContext();
    $socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
    $socket->connect("tcp://localhost:8000");
    $socket->send(json_encode($response));

}

Pusher File:

use Ratchet\ConnectionInterface;
use Ratchet\Wamp\WampServerInterface;

class Pusher implements WampServerInterface{

     public function onPostEntry($data){
         // Data that were sent by ZeroMQ through create_new_post() method
         $entry_data = json_decode($data);      

         // AND AFTER THIS, I DONT HAVE CLUE OF WHAT TO DO NEXT !!             

     }
}

Shell Script to run server:

require dirname(__DIR__) . '/vendor/autoload.php';

$loop   = React\EventLoop\Factory::create();
$pusher = new MyApp\Pusher;

// Listen for the web server to make a ZeroMQ push after an ajax request
$context = new React\ZMQ\Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:8000'); 
$pull->on('message', array($pusher, 'onBidEntry'));

// Set up our WebSocket server for clients wanting real-time updates
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); 
$webServer = new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(
        new Ratchet\WebSocket\WsServer(
            new Ratchet\Wamp\WampServer(
                $pusher
            )
        )
    ),
    $webSock
);

$loop->run();

Shell script only tells that it will serve in port 8080, however how would I mention my routes. Lets say I want the open connection in only the page 'mysite/allposts'. Also, what would be the script that I have to write in client side (a javascript file) and how to receive these new data by client side updating a particular DOM object.


Source: (StackOverflow)