在服务器事件上从服务器向客户端发送通知

时间:2014-06-22 19:29:15

标签: php ajax client-server

如何使用PHP从服务器向客户端发送消息,避免无关的Ajax调用。

这是一个想法:

  1. 用户:Alice进行了一项更改,并将其发送到服务器。

  2. 然后,服务器检查哪些用户不是最新的,如果没有,则调用一些代码将与更改有关的信息发送给Bob(在这种情况下,谁不是最新的)。

  3. 如何向Bob发送消息?

3 个答案:

答案 0 :(得分:20)

您可以使用Server Sent Events

这些经常过度看起来的腹板,表现更轻,单向。它们基本上允许客户端等待来自服务器的消息(然后您可以通过不同的通道(如AJAX)进行响应)

示例客户端代码:

var source = new EventSource('/newFile');

source.addEventListener('message', function(e) {
  // Use AJAX and pull new file here
}, false);

不幸的是,似乎(当然)有no IE support。可以使用诸如EventSource HQ之类的库来支持跨浏览器服务器发送的事件。它将抽象出需要处理恶魔的浏览器。

答案 1 :(得分:14)

您正在寻找的东西(现在)很常见,有时被称为“实时网络”。它能够让您的服务器端代码实时地将内容推送到连接的客户端。

这可以通过最新浏览器(和服务器)支持的一些新机制,以及其他一些并非真正设计用于实现这一目标的机制,但可以用作“黑客”来实现它。工作

您必须要了解的第一件事是您所要求的(服务器“向客户端”推送消息)不是网络(或者至少是http)的方式(或者更好,)打算工作。 经典Web是无状态,请求 - 响应,半双工:客户端启动通信,打开与服务器的连接,服务器提供服务,连接关闭。 过去,服务器无法向Web客户端发送消息:客户端(即您的浏览器)应该支持反向模型(提供它侦听的端点),成为有效的服务器。

这或多或少是WebSockets这样的新标准提供的(另一个标准值得一提的是Server-sent events (SSE);但是,它的支持甚至比WebSockets更稀缺,而且它们似乎更容易“流“发送单个邮件的内容。”

与HTTP不同,WebSocket提供全双工通信(任何一方都可以启动它),这正是您要寻找的。 WebSocket协议的正确版本(某些浏览器中存在较旧的错误实现)在Firefox 6,Safari 6,Google Chrome 14,Opera 12.10和Internet Explorer 10中实现。

那么,如果您的浏览器不支持WebSockets怎么办?你必须使用我前面提到的那些“技巧”。那些“诡计”属于Push technologies的unbrella。

特别是,常见的技术是长轮询。 就像名字所说,它不是“推”;长轮询是轮询,即“拉”技术,但它允许模拟推送机制。 通过长轮询,客户端完全按照正常的AJAX调用从服务器请求信息,除非它以更慢的频率发出HTTP / S请求(轮询)。

连接后,服务器(您的服务器,您的API:一个servlet,一个HTTP处理程序,一个REST控制器,无论如何!它通常与您为标准AJAX调用提供支持的机制相同)会发送一些信息已经是可用的更新;如果没有新内容,它会保持请求打开并等待响应信息变为可用,而不是发送空响应。

您有一个“传统的”客户端发起的请求,但是在服务器想要与您通信之前,它会被“暂停”。 一旦有东西,服务器就会向客户端发送一个响应(通过HTTP通道,仍然打开!),完成打开的HTTP请求。

可以使用其他技术(比如使用插件提供的套接字 - Silverlight,Java applet,Flash ..),但是再次使用它们需要正确的客户端(浏览器/插件组合)。

当然,你可以自己实现所有这些东西。我鼓励你尝试作为学习练习

对于您的生产代码,您最好使用一个封装所有这些概念和技术的库,例如SignalR(对于ASP.NET)Ratchet(对于PHP),Signal.IO(对于node.js),Faye(对于Ruby)....其中一些库将实现多种技术,选择基于客户端的最佳技术,自动回退到其他技术。他们真的给你带来了很多麻烦!

答案 2 :(得分:8)

正如评论中所说,您正在寻找的技术是WebSockets。它们是您在服务器和Web浏览客户端之间使用套接字(unix术语,用于基本的bidrectional管道)的一种方式。

虽然可以使用原始websocket api。我更喜欢使用像Socket.IO这样的库来为我抽象出讨厌的细节。

在正常情况下安装软件包之后(假设您正在使用节点)Socket.IO为您提供了许多不同的简单方法,例如集成到您的应用程序中的事件和广播。您也可以将它用作just a cross browser websocket(它为不支持websockets的浏览器实现后备长轮询)。

对于您的情况,您希望在服务器上更改文件时从服务器向客户端发送消息。

一个服务器端(Node.js):

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });

  // more stuff here
  if(somethingChanged) {
    socket.send(JSON.stringify({changed: true, file: 'file1.txt', newContent: 'Im fresh off the press yo!'});
  }
});

对于客户:

<script>
  var socket = io('http://localhost/');
  socket.on('connect', function () {
    socket.send('anything-new');

    socket.on('message', function (msg) {
      if(JSON.parse(msg).changed) {
        // Do stuff here
      }
    });
  });
</script>

虽然这是一个非常简单的例子,但希望能让你开始。