简体   繁体   中英

Real time notification with socket.io and redis

In my web app (symfony3) I try to integrate a real time notification system. I choose to done this with this configuration : server NodeJS server redis socket.io socket.io-php-emitter (php adaptater for emit notification directly from php)

app.js (server node)

var app = require('express')();
var http = require('http').Server(app);
var server = require('http').createServer();
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');

io.sockets.on('connection', function (socket) {
  console.log('user connected!');
});

io.adapter(redis({ host: 'localhost', port: 6379 }));
server.listen(8081, 'myhost');

test controller

public function testAction(Request $request)
{
    $notification = 'A message has been received by the server!<br />'
    $form = $this->createFormBuilder()->getForm();
    $form->handleRequest($request);
    if ($form->isValid()) {
        $redis = new \Redis();
        $redis->connect('127.0.0.1', '6379');
        $emitter = new SocketIO\Emitter($redis);
        $emitter->emit('notification', $notification);
        $response = new JsonResponse();
        $response->setData(array(
            'notification' => $notification
        ));
        return $response;
    }
    return $this->render('@PMPlatform/Test/test.html.twig', array(
        'form' => $form->createView()
    ));
}

client view

$(document).ready(function() {
    // Getting socket
    var socket = io('http://myhost:8081');
    // Listening on notification from server
    socket.on('notification', function (data) {
        $('.server').append('qsfdqsfdqsdfqsfdqsfd');
    });
    // Listener on form submit event
    $(document).on('submit', '.form', function(e) {
        e.preventDefault();
        $.ajax({
            type: 'POST',
            url: '/app_dev.php/test',
            data: $(this).serialize(),
            success : function(response){
                $('.client').append('A message has been sent to server from this client!<br />');
            },
            error : function(response){
                console.log('Something went wrong.');
            },
            cache: false
        });
        return false;
    });
});

Ok this simple test works fine : when I submit the form from the proper view, a notification is displayed to all client which are on this page.

1- Now I want to one user be able to send a notification only to one another user (when a user comment a post, the author of the post recieved a notification). How I can do this ?

2- If the author is not connected, How I can to save the notification to show it when the author connects back ?

For your first question, in the server you maintain in some way, redis for example, a list of all your connected clients by their sockets. But, the key thing here is to pass an id of the user when it connects to the server. Now you have your users in your socket.io server perfectly identified by their id.

io.sockets.on('connection', function (socket) {
  console.log(socket);
});

If you look at the socket object that comes with a connection, there you will have the id of the user that just got connected. Then when you want to send a notfiication to that user you just have to search in redis for the corresponding socket to the user id you want to send notification. When you instantiate your emitter $emitter = new SocketIO\\Emitter($redis); you will have to search in redis for that particular socket - search in redis by user id -

For the second question I won't go into websockets for this feature. Every time a user connects you will have to search in database if he has any pending notification, and send to him. This can be done for a small amount of users without incurring in a heavy computational usage, but this does not scale. For this purpose I will:

  • Search in redis for the connected user
  • If not connected, save into database the new notification.
  • When the user connects again, make a standard HTTP request to the API and send to him all the pending notifications, handling them and making necessary changes.

Hope it helps!

EDIT

I forgot to explain how you pass data on the connection. On the client just do: var socket = io('http://216.157.91.131:8080/', { userId: "myUserId" }); . Easy, isn't it?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM