Search code examples
phpwebsocketautobahnratchet

How to send and get data from the server using Ratchet


This is the first time I am using sockets and started off with Ratchet but I seriously cant fit my head into it. Still tried to join together some parts from the tutorial but facing some problems. Plus I would like to know how to use autobahn.js with it. The tutorials are not clear.

My Problem

1) How to send a message to all users except the current user stating " ... joined" and the '...' has to be the ip of the user.

I tried the following but it gives me error on the terminal.

public function onOpen(ConnectionInterface $conn) {
           // Store the new connection to send messages to later
           $this->clients->attach($conn);
           $this->send('new');
           echo "New connection! ({$conn->remoteAddress})\n";    
}

Call to undefined method MyApp\Chat::send()

2) What to do so that when a message is sent all the parties can view it including the one who is sending it (that's the way how every chat works)?

JS

var conn = new WebSocket('ws://localhost:8080');

conn.onopen = function(e) {
    //console.log("Connection established!");
    $("#chat_window #messages_list").append("<li class='join_disconnect'>127.0.0.1 Online</li>");
}
conn.onmessage = function(e) {
    //console.log(e.data);
    $("#chat_window #messages_list").append("<li class='thread'>"+e.data+"</li>");
}
conn.onclose = function(e) {
    //console.log("Connection Disconnected!");
    $("#chat_window #messages_list").append("<li class='join_disconnect'>127.0.0.1 Offline</li>");
};



$(document).ready(function(){

        disable_button();


        //EMERGENCY EXIT
        $('#exit').click(function(){
                window.location.replace('http://www.google.com');
        });


        //PREVENT BLANK INPUT
        $('#msg').on('keyup', function(e){

                if($(this).val().length>0){
                    enable_button();
                }
                else{
                    disable_button();
                }

        });

        //SEND MESSAGE
        $('#snd').click(function(){
            var thread = $('#msg').val();
            //console.log(thread);
            //conn.send(thread);
            $.ajax({
                type:'POST',
                url: './bin/send-message.php',
                data: {msg: thread},
                success: function(response){
                    //alert(response);
                    if(response!=1){
                        $('#msg').val('');
                        disable_button();
                    }
                }
            });
        });

        //ENABLE BUTTON
        function enable_button() {
            var element = document.getElementById('snd');
            $(element).addClass('active');
            element.style.pointerEvents = '';
        }

        //DISABLE BUTTON
        function disable_button() {
            var element = document.getElementById('snd');
            $(element).removeClass('active');
            element.style.pointerEvents = 'none';
        }


});

I know these are a lot of questions but I really want to know how. If there are any step by step easy to learn tutorials those are also welcome.


Solution

  • If you are trying to change example from the tutorial at the Rachet site, than for your first problem solution is:

    public function onOpen(ConnectionInterface $conn) {
        // first, you are sending to all existing users message of 'new'
        foreach ($this->clients as $client) {
            $client->send('new');
        }
        // than,
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
    
        echo "New connection! ({$conn->resourceId})\n";
    }
    

    Regarding your second question, if I get you right, you should send new messages to all connected clients, like this:

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
    
        foreach ($this->clients as $client) {
            // remove this check
            // if ($from !== $client) { 
                // The sender is not the receiver, send to each client connected
                // $client->send($msg);
            // }
    
            // just send to all
            $client->send($msg);
        }
    }
    

    Update: complete solution.

    In the Chat.php, you need to modify some methods:

    public function onOpen(ConnectionInterface $conn) {
        // first, you are sending to all existing users message of 'new'
        foreach ($this->clients as $client) {
            $client->send('<status>' . $conn->remoteAddress . ' Online</status>'); //here we are sending a status-message
        }
        // than,
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
    
            echo "New connection! ({$conn->remoteAddress})\n";
    }
    
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
    
        //send to others clients message about disconnected user
        foreach ($this->clients as $client) {
            $client->send('<status>' . $conn->remoteAddress . ' Offline</status>'); //here we are sending a status-message too
        }
    
        echo "Connection {$conn->remoteAddress} has disconnected\n";
    }
    

    in your js code, modify next method:

    conn.onmessage = function(e) {
        //console.log(e.data);
        var match = e.data.match(/^<status>(.*?)<\/status>$/i);
        if (match) {
            if (/\d+\.\d+\.\d+\.\d+ online/i.test(match[1])) {
                messages.append('<li class="join_connect">' + match[1] + "</li>");
            } else if (/\d+\.\d+\.\d+\.\d+ offline/i.test(match[1])) {
                messages.append('<li class="join_disconnect">' + match[1] + "</li>");
            }
        } else {
            messages.append('<li class="thread">' + e.data + "</li>");
        }
    };