服务器推送技术(Server Push)是最近Web技术中最热门的一个流行术语,它的别名叫Comet(彗星)。它是继AJAX之后又一个倍受追捧的Web技术。服务器推送技术最近的流行与AJAX有着密切的关系。本文详细介绍了服务器推送技术,希望对你有帮助。

推送技术Server Push的基础思想是将浏览器主动查询信息改为服务器主动发送信息。服务器发送一批数据,浏览器显示这些数据,同时保证与服务器的连接。当服务器需要再次发送一批数据时,浏览器显示数据并保持连接。以后,服务器仍然可以发送批量数据,浏览器继续显示数据,依次类推。

客户端拉曳(Client Pull)

在客户端拖曳技术中,服务器发送一批数据,在HTTP响应或文档头标记中插入指令,让浏览器“在5秒内再次装入这些数据”或“10秒内前往某URL装入数据”。当指定的时间达到时,客户端就按照服务器的指示去做,或者刷新当前数据,或者调入新的数据。

其实push 和 pull 这两种技术手段非常不同,但目的几乎一致,都是为了给最终用户方便的提供最新信息。

在服务器推送技术中,HTTP 连接一直保持着,直到服务器知道自己已结束发送数据并发送一个结束信号,或者客户端中断连接。而在客户端拖曳技术中,并不保持HTTP连接,相反,客户端被告知合时建立新连接,以及建立连接是获取什么数据。

在服务器推送中,奇妙之处在于“multipart/mixed”格式的MIME,它能够使一个报文(或HTTP响应)包含许多数据项、在客户端拖曳中,奇妙之处在于HTTP响应头标(或等效的HTML元素),它能告知客户端在指定的延时时间后执行何种动作。

服务器推送通常效率要比客户端拖曳效率高,因为它不必为后续数据建立新的连接。由于始终保持连接,即使没有数据传输时也是这样,因此服务器必须愿意分配这些TCP/IP端口,对于TCP/IP端口数有限的服务器这将是一个严重的问题。

客户端拖曳效率低,因为这必须每次为传送数据建立新的连接。但是它不必始终保持连接。

在实际情况中,建立HTTP连接通常需要花费相当多的时间,多达一秒甚至更多。因此从性能上考虑,服务器推送对于最终用户更有吸引力,特别是对于需要经常更新信息的情况下。

服务器推送技术的优势在于相对客户端拖曳更容易控制。与客户端拖曳相比,服务器在每次推送时都保持一个连接,但可以随时关闭其中的任何连接,而无需在服务器上设置特殊算法。相反,客户端拖曳需要为处理将客户端拖曳请求与特定最终用户匹配等情况而使用复杂的算法。

如果实现服务器推送的CGI程序是使用Shell脚本语言编写的,可能会遇到一些问题。例如,当客户端最终用户中断连接时,Shell程序通常无法注意到这一点,导致资源浪费。为了解决这个问题,可以使用Perl或C等其他编程语言来编写这类CGI程序,以便在用户中断连接时能够结束运行。

在服务器推送中,多个响应之间的连接始终保持打开状态,使服务器能够在任何时间发送更多数据。这带来了明显的好处,即服务器可以完全控制更新数据的时间和频率。此外,由于始终保持连接,这种方法具有较高的效率。然而,缺点是保持连接状态会消耗服务器端的资源,且服务器推送容易被中断。

接下来简要介绍服务器推送技术。当服务器响应请求时,HTTP使用MIME报文格式来封装数据。通常情况下,一个HTTP响应只能包含一个数据块。但是,MIME提供了一种机制,使得一个报文(或HTTP响应)可以表示多个数据块,这种机制被称为“multipart/mixed”的标准MIME类型。multipart/mixed报文的基本格式如下:

```

Content-type: multipart/mixed; boundary=ThisRandomString

--ThisRandomString

Content-type: text/plain

第一个对象的数据。

--ThisRandomString

Content-type: text/plain

第二个对象的数据。

--ThisRandomString--

```

上述报文包括两个数据块,它们的类型都是“text/plain”。最后一个“ThisRandomString”后的两条短线(--)表示报文结束,后面没有数据。

对于服务器推送,可以使用一个名为“multipart/x-mixed-replace”的变种。在这里,“x-”表示该类型属于实验性。而“replace”表示每个新数据块都会替换前一个数据块。换句话说,新数据不是附加到旧数据之后,而是替代它。

下面是实际使用的“multipart/x-mixed-replace”类型:

```

Content-type: multipart/x-mixed-replace; boundary=ThisRandomString

--ThisRandomString

Content-type: text/plain

第一个对象的数据

--ThisRandomString

Content-type: text/plain

第二个(最后一个)对象的数据。

--ThisRandomString--

```

使用这一技术的关键是,服务器并不是推送整个“multipart/x-mixed-replace”报文,而是每次发送后数据块。HTTP连接始终保持,因而服务器可以按自己需要的速度和频率推送新数据,两个数据块之间浏览器仅需在当前窗口等候,用户甚至可以到其他窗口做别的事情,当服务器需要发送新数据时,它只是源传输管道发送数据块,客户端相应的窗口进行自我更新。

在服务器推送技术中,“multipart/x-mixed-replace”类型的报文由唯一的边界线组成,这些边界线分割每个数据块。每个数据块都有自己的头标,因而能够指定对象相关的内容类型和其他信息。由于“multipart/x-mixed-replace”的特性是每一新数据块取代前一数据对象,因而浏览器中总是显示最新的数据对象。

“multipart/x-mixed-replace”报文没有结尾。也就是说,服务器可以永远保持连接,并发送所需的数据。如果用户不再在浏览器窗口中显示数据流,或者浏览器到服务器间的连接中间(例如用户按“STOP”按钮),服务器的推送才会中断。这是人们使用服务器推送的典型方式。

当浏览器发现“Content-type”头标或到达头标结束处时,浏览器窗口中的前一个文档被清除,并开始显示下一个文档。发现下一个报文边界时,就认为当前数据块(文档)已经结束。

总之,服务器推送的数据由一组头标(通常包括“Content-type”)、数据本身和分割符(报文边界)三部分组成。浏览器看到分割符时,它保持状态不变,直到下一个数据块到达。将以上概念进行用编程方法实现,就可以得到实际的服务器推送程序。例如,下面的Unix shell程序将使浏览器每5秒显示一次服务器上的进程列表:

```bash

#!/bin/sh

while true; do echo "Processes on server"; sleep 5; done

```

以下是重构后的代码:

```php

echo "HTTP/1.1 200

Content-type: multipart/x-mixed-replace;boundary=--ThisRandomString--

--ThisRandomString--";

while (true) {

echo "Content-type: text/html

h2Processes on this machine updated every 5 seconds/h2

time:";

date();

echo "p";

echo "plaintext";

ps -el;

echo "--ThisRandomString--";

sleep(5);

}

```

注意事项:

1. 请确保边界参数没有空格,包括冒号后面的空格。NCSA HTTPD只能将不带空格字符的字符串作为内容类型。如果在内容类型行中存在空格(冒号后面的空格除外),空格后的任何文本都会被删除。所以正确的格式应该是:`Content-type: multipart/x-mixed-replace;boundary=ThisRandomString` 而不是 `Content-type: multipart/x-mixed-replace; boundary=ThisRandomString`。