Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 节点+;Redis+;PHP实时性问题_Node.js_Sockets_Redis_Socket.io_Node Redis - Fatal编程技术网

Node.js 节点+;Redis+;PHP实时性问题

Node.js 节点+;Redis+;PHP实时性问题,node.js,sockets,redis,socket.io,node-redis,Node.js,Sockets,Redis,Socket.io,Node Redis,我正在NodeJS+Redis+PHP中构建一个Pub/Sub服务器,在深入研究这个主题并开始构建一些我在过程中遇到的困惑之后 示例场景: <input type="text" id="message"> <button id="sendMessage">Send alert</button> 5个用户通过NodeJs正确连接到插座 其中一个用户单击按钮向除他以外的所有连接用户发送自定义警报 Php通过调用ajax接收警报消息(示例) Php发布回Redi

我正在NodeJS+Redis+PHP中构建一个Pub/Sub服务器,在深入研究这个主题并开始构建一些我在过程中遇到的困惑之后

示例场景:

<input type="text" id="message">
<button id="sendMessage">Send alert</button>
  • 5个用户通过
    NodeJs
    正确连接到插座
  • 其中一个用户单击按钮向除他以外的所有连接用户发送自定义
    警报
  • Php通过调用ajax接收警报消息(示例)
  • Php发布回Redis
  • Redis接收事件并触发socket.io以广播事件
设置视图:

<input type="text" id="message">
<button id="sendMessage">Send alert</button>
用于与redis通信的Php服务器端

var socket = io.connect('http://127.0.0.1:3000/');

socket.on('notification', function (data) {

    alert(data.message);
    console.log('message received');
});

// Ajax event
$(document).on('click','#sendMessage', function(){

    $.ajax({
      url: '/send/notification',
      method: 'POST',
      type: 'JSON',
      data: { message: $('#message').val() },
      success:function(data)
      {
        console.log('message sent');
      }
    })
});
$message = $_POST['message'];
$redis = new Predis\Client();
$redis->publish('notification',$message);
NodeJs

var socket = io.connect('http://127.0.0.1:3000/');

socket.on('notification', function (data) {

    alert(data.message);
    console.log('message received');
});

// Ajax event
$(document).on('click','#sendMessage', function(){

    $.ajax({
      url: '/send/notification',
      method: 'POST',
      type: 'JSON',
      data: { message: $('#message').val() },
      success:function(data)
      {
        console.log('message sent');
      }
    })
});
$message = $_POST['message'];
$redis = new Predis\Client();
$redis->publish('notification',$message);
此时,在我的
NodeJs
服务器上,我将在redis中监听消息事件,然后将事件广播到套接字,但这是我遇到的第一个问题

var http = require('http');
var app  = http.createServer();
var io   = require('socket.io')(app);
var redis = require('redis');

app.listen(3000,'127.0.0.1',function(){
    console.log("listening:", app.address().port, app.address().address);
});

io.on('connection', function(client){
    var redisClient = redis.createClient();

    redisClient.subscribe('notification');

    redisClient.on("message",function(channel,data){

          // This line should broadcast to all the client except the sender
          socket.broadcast.emit(channel,JSON.parse(data));

          console.log(channel);
    });
});
问题 此时,我可以在终端5上看到
console.log()
channel
日志“notification”Why 5

当socket.io
广播该事件时,它会执行5次,在这种情况下,会向
客户端发送5
警报()
,并向
发送方发送4,而不是向所有客户端发送0

时间取决于连接了多少用户,我真的不明白我错过了什么,因为这不应该是正确的行为

我已经尝试将
redisClient
的创建和
io.on('connection')
之外的频道订阅放在('connection')上,但没有成功,结果是一样的


另一项测试

如果我
广播
插座连接上的事件,如下所示:

io.on('connection', function(client)
{
     client.broadcast.emit('notification','hello');
});

它工作正常,所以我认为是redis的问题。任何建议都将不胜感激。

您连接了5个客户端,因此“连接”事件将触发5次。 因此,redis有5个侦听器,然后全部进行广播

有两种方法可以正确执行此操作:

a) 每个连接1个侦听器,仅向连接发送消息

io.on('connection', function(socket){
    var redisClient = redis.createClient();

    redisClient.subscribe('notification');

    redisClient.on("message",function(channel,data){

          // This line should broadcast to only the current connection
          socket.emit(channel,JSON.parse(data));

          console.log(channel);
    });
});
b) 1个全局侦听器,向所有客户端广播

var redisClient = redis.createClient();

redisClient.subscribe('notification');

redisClient.on("message",function(channel,data){

   // This line should broadcast to all the client except the sender
   io.sockets.emit(channel,JSON.parse(data));

   console.log(channel);
});

我更喜欢方法b),因为它只需要一个redis连接。

我在一个项目中也做了同样的事情。唯一的区别是我从node.js发布了通知,但我没有收到任何问题。只有广播打开了套接字。

非常感谢你的回答,我对它做了同样的实验。使用方法b)它向所有客户端(甚至是发送方)发出它不应该发出的消息。如果我使用
broadcast
方法,它会发疯,每个发送2个通知。在方法a)中,它向所有客户端发出相同的消息,但是您所说的具有多个连接。如何将方法b)与
broadcast
方法结合使用,将事件发送到除发送方之外的所有客户端?如果你不介意的话,我想和你聊聊,这对我很有用。有点离题,但我不太清楚为什么要使用PHP。您只需调用一个NodeJS Web服务来发布消息,就可以去掉开发堆栈中的一个附加部分(除非您不需要PHP来完成其他事情)。。。