How to perform real-time information exchange

1144 Views
|
27 Nov 2015
|
4 min
author avatar
Yana P.
Copywriter

Sooner or later we all may face the task, which requires to perform the real-time information exchange. I encountered this problem working on the project written in a great framework Yii. The task seemed to be interesting and at first glance rather simple.

User A sends data to the processing by POST method (through existing API /userData). After some time, user B in real time (without page reload) receives a request in the form of a dialog box to confirm user's A data processing. Further, user B simply confirms or cancels the action.

Technologies in use

Having faced with such a non-trivial task, first of all, I began the search for ready-made solutions enabling to exchange information in real time in PHP. As it turned out that the implementation in PHP was not so simple. Taking into account the limited time, websockets implementation in PHP seemed to be a dangerous idea. Likewise, the use of phpdaemon and ratchet libraries was unreliable and time-consuming (perhaps the reason of such bias was the lack of experience with these libraries).

Further searching has led me to Node.js technology in combination with Socket.io library. It was known as a proven and time-tested technology, besides, it was a perfect solution for this particular task.

Still the entire project was developed in PHP and the whole functionality related with user's data sending to the server was already implemented. And the time limits, again, prevented me from remaking the server to Node.js. The solution came by itself:

  • Deploy a Node.js server
  • Send a request from PHP to Node.js 
  • Send through socket to the user 
Well, let's start :)

Steps to implement the project

There were no problems with the installation of the Node.js server. All information can be found on the official website https://nodejs.org.

In the root directory of the project, we create a folder nodeServer and a package.json file in it:

{
  "name": "nodeJs server",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "socket.io": "^1.3.5",
    "body-parser": "~1.12.0",
    "express": "~4.9.0"
  }
}

Then everything is simple. Write a command npm install in the console to install the libraries.

Create a file app.js, wherein we initialize and run our server.

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());
//set port
app.set('port', process.env.PORT || 7777);
var server = app.listen(7777, function() {
    console.log('info', "Web server successfully started at port " + server.address().port);
});

Start the server in the console

npm start

If you see the message "info Web server successfully started at port 7777", then everything is successful and the server is running.

We proceed to initializing of our socket. Add the code to initialize the socket:

var io = require('socket.io')(server);
io.sockets.on('connection', function (socket) {
    console.log('new connection');
    socket.on('disconnect', function (data) {
console.log('socket disconnect');
    });
});

Let's get down to client's part writing. First of all, we connect socket.io library.

Open the file protected/views/main.php and add

<script src="socket.io.js"></script>

Then we need to connect the server through to the socket

var socket = io.connect('http://localhost:7777');

Let's check what we've got. Start the server and look what the console outputs at the application launch. If you have done everything correctly, the page is loaded, you should see the message "new connection" and the message "socket disconnect", respectively, when the app is closed.

Next, we modify the project so that we can see what user is connected to us. We announce an array where we are going to keep our connections:

var clients = [];

Create a new event on the server

socket.on('newUser', function(data) {
        socket.userId = data.id;
        clients[data.id] = socket;
    });
Modify the event 'disconnect'

socket.on('disconnect', function (data) {
if ( !socket.userId )
            return;
        delete clients[socket.userId];
    });

And also make the appropriate changes on the client

socket.emit('newUser', {id:73});
where '73' is our current user.

Now let's proceed to the final section: directly to the interaction between PHP and Node.js with Socket.io.

Create on the Node.js server an API to send the confirmation request to the user.

Here is the code to send the request to the user through the socket:

app.post('/confirm', function(req, res) {
    var userId = req.body.userId;
    if (typeof clients[userId] != 'undefined') {
        clients[userId].emit('confirmDialog', req.body);
    }
    res.status(200);
    res.end();
});

Add processing on the client

socket.on('confirmDialog', function(data){
alert('success');
})

Write a function that will send a request to Node.js through curl

function sendNodeJsRequest($userId)

{
 $url = 'http://localhost:7777/confirm';
            $fields = array(
        'userId' => $userId
    );
    $data = json_encode($fields);
    //open connection
    $ch = curl_init();
    //set curl option
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data)));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    //execute
    $resp = curl_exec($ch);
    //close connection
    curl_close($ch);
}

Then we will just call our method when processing the information of user A (/userData).

If you have done everything correctly when you start a project, you will see the following case. When sending a POST request to the API (/userData) our method sendNodeJsRequest ($userId) will be called, where $userId is a user ID whom we need to transfer information in real time (user B). The method in its turn will send a request to our Node.js server, and the server will send information in real time to the client through the socket. As a result, the user will see the alert with the word 'success'.

This is just one way to solve this problem. And if you have no opportunity to install the Node.js on the server, you may want to try such libraries as phpdaemon and ratche. However, this method gives excellent results as well as the possibility of the real-time interaction between the server written in PHP and the client.

Find out what new possibilities Node.js 4 has brought to developers here.

Attachment: The code of Node.js server

The final app.js code of Node.js server

var express = require('express');
var bodyParser = require('body-parser');

var app = express();

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

//get request from php
app.post('/confirm', function(req, res) {
    console.log();
    var userId = req.body.userId;
    if (typeof clients[userId] != 'undefined') {
        clients[userId].emit('confirmDialog', req.body);
    }
    res.status(200);
    res.end();
});
//set port
app.set('port', process.env.PORT || 7777);
var server = app.listen(7777, function() {
    console.log('info', "Web server successfully started at port " + server.address().port);
});

var io = require('socket.io')(server);
var clients = [];
io.sockets.on('connection', function (socket) {
    //When get current user
    socket.on('newUser', function(data) {
         socket.userId = data.id;
        clients[data.id] = socket;
    });
    
    socket.on('disconnect', function (data) {
        if ( !socket.userId )
            return;
        delete clients[socket.userId];
    });
});

Client's code:

var socket = io.connect('http://localhost:7777');
socket.emit('newUser', {id:73});
socket.on('confirmDialog', function(data){
                alert('success');
})

Rate this article!

An image An image
Bad!
An image An image
Strange!
An image An image
Boring!
An image An image
Good!
An image An image
Love it!
(1444 ratings, average: 4.69 out of 5)
Latest articles
Article preview image
Top 5 cybersecurity frameworks in healthcare field
Calendar icon
18 Jul 2019
Clock icon
10 min
Article preview image
15 software outsourcing companies by size
Calendar icon
16 Jul 2019
Clock icon
10 min
Article preview image
Estimating web application development cost
Calendar icon
11 Jul 2019
Clock icon
9 min
Back to top
As s part of our team, be ready for:
An image
Competitive Base Salary
An image
Comprehensive Benefits
An image
Great Work Environment
An image
Drug Free Workplace
Tell us more about yourself