Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Websockets PHP / AJAX / Javascript refresh client

I'm using websockets with PHP and some Javascript. I display some information from my database to my client. My goal is to refresh the client when an information has insert into my database. To insert some data in my database, I send a post request from my PC.

At the moment, I can refresh the client to call a function every 10 seconds. But I would like to refresh only if, on that page, a POST request is send.

Here is something that can help you to understand:

enter image description here

  1. The client's connecting to the web page.
  2. A SQL select is execute on my database
  3. The result is received and displayed on the web page.
  4. The client is connected (via websockets) and see the information from the database.
  5. Me. If I insert an information on the database, I send a POST request (not from a HTML form, no submit, just a POST request, like if I used Postman to test a webservice). When the request is send, refresh the client by calling a Javascript function...

Here is what I've done:

  • index.php (Page where the information are displayed)

    $(document).ready(function(){
    
        //create a new WebSocket object.
        var wsUri = "ws://localhost:9000/server.php";
        websocket = new WebSocket(wsUri);
    
        websocket.onopen = function(ev) { // connection is open
            $('#message_box').append("<div class=\"system_msg\">Connected!</div>"); //notify user
        }
    
        // Call this function every 10 sec to refresh the client
        window.setInterval(function(){
            displayInfo(1);
        }, 10000);
    
        websocket.onmessage = function(ev) {
            var msg = JSON.parse(ev.data); //PHP sends Json data
            $("#infos").html(msg.message);
        };
    
        websocket.onerror   = function(ev){$('#message_box').append("<div class=\"system_error\">Error Occurred - "+ev.data+"</div>");};
        websocket.onclose   = function(ev){$('#message_box').append("<div class=\"system_msg\">Connection Closed</div>");};
    });
    
    function displayInfo(r) {
    
        $.post("infos.php",
            { refresh : r},
            function(data){
    
                var msg = {
                    message: data
                };
    
                //convert and send data to server
                websocket.send(JSON.stringify(msg));
            }
        );
    }
    
  • infos.php : Where I execute the SQL select request (works fine)

  • server.php : Where the code for the server side is. (works fine)

Well. I really don't know how can I achieve this. How to inform and call the function displayInfo(r); if a POST request is send to this page.

Any help is very appriciated. Thank you in advance.

Regards, Lapinou.

like image 439
Lapinou Avatar asked May 03 '14 17:05

Lapinou


People also ask

What is a WebSocket in PHP?

The WebSocket is used to create a bridge to send or receive messages from the PHP chat server. In the web world, we generally use HTTP request methods to communicate between the client and server side.

Can I run Ajax over WebSockets?

In this tutorial, we show how to easily run AJAX over WebSockets for browser to server communication. We also go over situations where AJAX should not be used and when real time messages sent over a WebSocket connection is preferred over using AJAX. You are probably thinking why would I want to run AJAX over WebSockets.

How do I use sockets in PHP chat?

In this chat example, we use sockets to communicate with the server. For establishing a socket connection between the client and the server, we use the WebSocket protocol (ws://) to specify the address of the PHP page where the WebSocket handshake is handled.

What are the advantages of WebSocket over HTTP?

The data can be passed in both directions as “packets”, without breaking the connection and additional HTTP-requests. WebSocket is especially great for services that require continuous data exchange, e.g. online games, real-time trading systems and so on.


Video Answer


1 Answers

I've seen the server.php from the link you've provided, and it simply:

  1. Accepts incoming connections
  2. Loops through all connected sockets
  3. If any of these sockets has data, it replies to every other client.

You need to alter this loop and add another source for messages, and you have 2 options. You can pool a DB or open another TCP socket and read from there.

However, the best solution is to use NodeJS with Socket.io and DNode (very elegant solution that works cross-browser and is not that difficult), but you need to be able to install NodeJS on your server. I can provide samples if you want.


EDIT: Here it goes my way of doing it.

I'll assume you are familiar with Debian based distributions (I'm going to install things with APT). First I'll explain some things:

  • NodeJS is a server-side javascript interpreter that will run our socket part. In fact, we will use both PHP and NodeJS (the latter only for updating clients, so your existing code will not change much)
  • NPM is a command line utility (that comes with NodeJS). Its main purpose is for installing packages (Socket.io and DNode are NPM packages)
  • Socket.io is a wrapper around WebSockets that make it works cross-browser. It also contains the server-side handling functions
  • DNode is an RPC for communicating with other languages/servers (in this case, with our PHP script)

First we install NodeJS. The version on Ubuntu repo's is veeery old, so we add a PPA from here:

sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install node

This will install NodeJS and NPM. More info here.

Now cd into your working directory and create this file: server.js

//import libraries
var io = require('socket.io');
var dnode = require('dnode');

var clients = []; //this array will hold all connected clients

var srv = io.listen(8080, { log: false }); //this port must be different from apache
srv.sockets.on('connection', function(socket){
    console.log("Client connected.");
    clients.push(socket);

    //this will be called when a javascript client sends us something. you can delete this if you don't need it
    socket.on('message', function(data){
        console.log(data); 
    });

    socket.on('disconnect', function(){
        console.log("Lost client.");
        var i = clients.indexOf(socket);
        clients.splice(i, 1); //remove from array
    });
});

var dnode_server = dnode({
    //expose a "send" function
    send: function(data, cb){
        for(i = 0; i < clients.length; i++){
            clients[i].emit('update', { //send an "update" message to all connected clients
                title: data.title, //some data
                text: data.text
            });
        }
        cb(null, false); //inform PHP that the processing is done. You can also return something
    }
    //you can have multiple functions here
});
dnode_server.listen(5004); //this port should not be accessible from the ouside

Next, install required libraries:

npm install socket.io
npm install dnode

You can run this script using node server.js

Now we need to edit the clientside javascript. Import Socket.io using this:

<script type="text/javascript" src="http://YOURHOSTNAME:SOCKETIOPORT/socket.io/socket.io.js"></script>

Then use it like this:

socket = io.connect('http://YOURHOSTNAME:SOCKETIOPORT');
socket.on('connect', function(data){
    alert('Connected!');
});
socket.on('disconnect', function(){
    alert('Disconnected :( are you offline?');
});
socket.on('update', function(data){ //our function call
    alert(data.title + " " + data.text);
});

You can send data to server like on NodeJS:

socket.emit('message', {foo: 'bar'});

Finally, you want to trigger "update" on all connected clients from a PHP script. For this, we need a PHP library for interfacing DNode. You can find it here and its usage is very simple:

$dnode = new \DnodeSyncClient\Dnode();
$connection = $dnode->connect('localhost', 5004);
$connection->call('send', array(array(
    'title' => "My awesome title",
    'text' => "My awesome text"
)));

Calling this PHP script will send title and text to your server.js that will broadcast everything to your connected clients.

Hope this helps!

like image 139
JohnKiller Avatar answered Nov 10 '22 06:11

JohnKiller