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

时间:2022-08-29 09:53:26

How can I send a message from server to client with PHP, avoiding extraneous Ajax calls.

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

Here is the idea:

这是一个想法:

  1. User: Alice makes a change which gets sent to the server.

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

  2. The Server then checks to see which users are not up to date, and if not calls some code to send the information pertaining to the change to Bob (who is not up to date in this case).

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

How do I send Bob the message?

如何向Bob发送消息?

3 个解决方案

#1


18  

You can use Server Sent Events.

您可以使用服务器发送事件。

These are the often over looked cousin of websockets that are lighter weight and one way. They essentially allow the client to wait for a message from the server (which you can then respond to via a different channel such as AJAX)

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

Example Client Code:

示例客户端代码:

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

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

Unfortuantely it seems (of course) that there is no IE support. One could use a library such as EventSource HQ to support cross browser server sent events. It will abstract away needing to handle the devil's browser.

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

#2


13  

What you are looking for is something which is (now) quite common, and is sometimes called "real-time web". It's the ability to have your server-side code push content to the connected clients as it happens, in real-time.

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

This is possible through a couple of new mechanisms which are supported by newest browsers (and servers), and by some other mechanisms which weren't really designed to do that, but which can be used as "hacks" to make it work.

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

The first thing you have to understand is that what you are asking for (a server "pushing" a message to a client) is not how the web (or, at least, http) is (or better, was) intended to work. The classic web is stateless, request-response, half-duplex: the client initiates the communication, opens a connection to the server, the server serve something, and the connection is closed. And there used to be no way for a server to send a message to a web client: the client (i.e. your browser) should support the reverse model (offering an endpoint on which it listens), becoming effectively a server.

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

This is, more or less, what newer standards like WebSockets offer (another standard worth mentioning is Server-sent events (SSE); however, its support is even scarcer than WebSockets, and they seem more apt to "stream" content than sending single messages).

这或多或少是像WebSockets这样的新标准提供的(另一个标准值得一提的是服务器发送事件(SSE);但是,它的支持甚至比WebSockets更稀缺,并且它们似乎比发送单个“流”内容更容易消息)。

Unlike HTTP, WebSocket provides full-duplex communication (either party can initiate it), which is what you are looking for. The correct version of the WebSocket protocol (an older, buggy implementation exist in some browsers) is implemented in Firefox 6, Safari 6, Google Chrome 14, Opera 12.10 and Internet Explorer 10.

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

So, what if your browser does not support WebSockets? You have to use those "tricks" I mentioned earlier. Those "trick" fall under the unbrella of Push technologies.

那么,如果您的浏览器不支持WebSockets怎么办?你必须使用我前面提到的那些“技巧”。这些“伎俩”属于Push技术的喧嚣。

In particular, a common technique is long polling. Like the name says, it is not "push"; long polling is polling, i.e. a "pull" technique, but it allows to emulate a push mechanism. With long polling, the client requests information from the server exactly as in a normal AJAX call, except it issues its HTTP/S requests (polls) at a much slower frequency.

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

Upon connection, the server (your server, your API: a servlet, an HTTP handler, a REST controller, whatever! It is usually the same mechanism with which you provide support for your standard AJAX calls) sends some info if there is already an update already available; if there is nothing new, instead of sending an empty response, it holds the request open and waits for response information to become available.

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

You have a "traditional" client-initiated request, but that is put "on hold" until there is something that the server wants to communicate to you. Once there is something, the server sends a response (via the HTTP channel, still open!) to the client, completing the open HTTP Request.

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

Other techniques (like using sockets provided by plugins - Silverlight, Java applets, Flash..) can be used, but then again for exploiting them you need the correct client (brower/plugin combo).

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

Of course, you could implement all this stuff by yourself. And I encourage you to try as a learning exercise.

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

For your production code, you better use a library that encapsulates all these concepts and techniques, like SignalR (for ASP.NET) Ratchet (for PHP), Signal.IO (for node.js), Faye (for Ruby).... Some of these libraries will implement more than one technique, choose the best technique based on the client, falling back to other ones automatically. They really spare you a lot of trouble!

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

#3


8  

As was said in the comments the technology that you are looking for is WebSockets. They are a way for you to have a socket (a unix lingo term for essential a bidrectional pipe) between your server and the web browsing client.

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

While one can work with the raw websocket api. I prefer to use a library like Socket.IO to abstract away the nasty details for me.

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

After installing the package as one normally would (assuming you're using node) Socket.IO gives you many different easy ways such as events and broadcasts in integrate into your application. You can also just use it as a just a cross browser websocket (it implements fallback long polling for browsers that don't support websockets).

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

For your case you would want to send a message from the server to the client when ever a file is changed on the server.

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

One the server side (Node.js):

一个是服务器端(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!'});
  }
});

For the client:

对于客户:

<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>

While that is a very bare example it's hopefully enough to get you started.

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

#1


18  

You can use Server Sent Events.

您可以使用服务器发送事件。

These are the often over looked cousin of websockets that are lighter weight and one way. They essentially allow the client to wait for a message from the server (which you can then respond to via a different channel such as AJAX)

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

Example Client Code:

示例客户端代码:

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

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

Unfortuantely it seems (of course) that there is no IE support. One could use a library such as EventSource HQ to support cross browser server sent events. It will abstract away needing to handle the devil's browser.

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

#2


13  

What you are looking for is something which is (now) quite common, and is sometimes called "real-time web". It's the ability to have your server-side code push content to the connected clients as it happens, in real-time.

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

This is possible through a couple of new mechanisms which are supported by newest browsers (and servers), and by some other mechanisms which weren't really designed to do that, but which can be used as "hacks" to make it work.

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

The first thing you have to understand is that what you are asking for (a server "pushing" a message to a client) is not how the web (or, at least, http) is (or better, was) intended to work. The classic web is stateless, request-response, half-duplex: the client initiates the communication, opens a connection to the server, the server serve something, and the connection is closed. And there used to be no way for a server to send a message to a web client: the client (i.e. your browser) should support the reverse model (offering an endpoint on which it listens), becoming effectively a server.

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

This is, more or less, what newer standards like WebSockets offer (another standard worth mentioning is Server-sent events (SSE); however, its support is even scarcer than WebSockets, and they seem more apt to "stream" content than sending single messages).

这或多或少是像WebSockets这样的新标准提供的(另一个标准值得一提的是服务器发送事件(SSE);但是,它的支持甚至比WebSockets更稀缺,并且它们似乎比发送单个“流”内容更容易消息)。

Unlike HTTP, WebSocket provides full-duplex communication (either party can initiate it), which is what you are looking for. The correct version of the WebSocket protocol (an older, buggy implementation exist in some browsers) is implemented in Firefox 6, Safari 6, Google Chrome 14, Opera 12.10 and Internet Explorer 10.

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

So, what if your browser does not support WebSockets? You have to use those "tricks" I mentioned earlier. Those "trick" fall under the unbrella of Push technologies.

那么,如果您的浏览器不支持WebSockets怎么办?你必须使用我前面提到的那些“技巧”。这些“伎俩”属于Push技术的喧嚣。

In particular, a common technique is long polling. Like the name says, it is not "push"; long polling is polling, i.e. a "pull" technique, but it allows to emulate a push mechanism. With long polling, the client requests information from the server exactly as in a normal AJAX call, except it issues its HTTP/S requests (polls) at a much slower frequency.

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

Upon connection, the server (your server, your API: a servlet, an HTTP handler, a REST controller, whatever! It is usually the same mechanism with which you provide support for your standard AJAX calls) sends some info if there is already an update already available; if there is nothing new, instead of sending an empty response, it holds the request open and waits for response information to become available.

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

You have a "traditional" client-initiated request, but that is put "on hold" until there is something that the server wants to communicate to you. Once there is something, the server sends a response (via the HTTP channel, still open!) to the client, completing the open HTTP Request.

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

Other techniques (like using sockets provided by plugins - Silverlight, Java applets, Flash..) can be used, but then again for exploiting them you need the correct client (brower/plugin combo).

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

Of course, you could implement all this stuff by yourself. And I encourage you to try as a learning exercise.

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

For your production code, you better use a library that encapsulates all these concepts and techniques, like SignalR (for ASP.NET) Ratchet (for PHP), Signal.IO (for node.js), Faye (for Ruby).... Some of these libraries will implement more than one technique, choose the best technique based on the client, falling back to other ones automatically. They really spare you a lot of trouble!

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

#3


8  

As was said in the comments the technology that you are looking for is WebSockets. They are a way for you to have a socket (a unix lingo term for essential a bidrectional pipe) between your server and the web browsing client.

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

While one can work with the raw websocket api. I prefer to use a library like Socket.IO to abstract away the nasty details for me.

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

After installing the package as one normally would (assuming you're using node) Socket.IO gives you many different easy ways such as events and broadcasts in integrate into your application. You can also just use it as a just a cross browser websocket (it implements fallback long polling for browsers that don't support websockets).

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

For your case you would want to send a message from the server to the client when ever a file is changed on the server.

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

One the server side (Node.js):

一个是服务器端(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!'});
  }
});

For the client:

对于客户:

<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>

While that is a very bare example it's hopefully enough to get you started.

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