# 3.8 服務器推送
## 3.8 服務器推送
服務器推送(Server Push)是一種由服務器發起的消息推送技術,用于把服務器端產生的消息*即時地*推送給客戶端,典型的應用場景如Web聊天、微博消息等。
服務器推送與通常的HTTP請求不同——后者都是由客戶端發起的,但實際上在WebSocket出現以前,Web原生的服務器推送技術都是用普通的HTTP來模擬的,如果不借助于Flash或者Applet這樣的第三方工具的話。下面讓我們來了解一些主要的推送技術,并重點了解一下WebSocket。
### 輪詢(polling)
這是一種最簡單的模擬推送技術:客戶端以一定時間間隔定期向服務器發起HTTP請求。
這種技術簡單、實用,但如果間隔時間太長(如幾分鐘)則即時性不高,間隔太短(如幾秒鐘)則對服務器的壓力較大(考慮到同時有N個用戶的話)。所以對它的應用要考慮具體場景。
### 長輪詢(long polling)
這也是一種模擬推送技術,其基本方式是:
1. 客戶端發起一個HTTP請求;
2. 如果服務器有更新則返回更新,否則阻塞;
3. 客戶端在收到更新后立即發起一個新的HTTP請求,如此循環往復
長輪詢可以通過Ajax實現。它是一種在WebSocket出現之前或當后者不可用時的一種有效的服務器推送技術,屬于Comet技術的一種。但這種技術,包括Comet的其他技術,在實現上比較復雜,參考這里了解更多:
- [https://en.wikipedia.org/wiki/Comet\_(programming)](https://en.wikipedia.org/wiki/Comet_(programming))
- <https://www.ibm.com/developerworks/cn/web/wa-lo-comet/>
### WebSocket
WebSocket作為HTML5的一部分在2008年被提出,如今已經被主要的瀏覽器實現。它可以讓Web服務器和Web客戶端通過一個全雙工(full-duplex)的TCP連接進行通訊。TCP即傳輸控制協議(Transmission Control Protocol),它提供一種穩定的端到端傳輸。TCP連接就象一個管道,任何一端都可以向其中讀/寫數據。
一個簡單的例子如下[1](#fn_1):
```
<meta charset="utf-8" />
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init()
{
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket()
{
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt)
{
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt)
{
writeToScreen("DISCONNECTED");
}
function onMessage(evt)
{
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
function onError(evt)
{
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message)
{
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message)
{
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
```
你可以把以上代碼保存在一個文件中,用瀏覽器打開就能看到效果。
在上面的代碼中:
```
var wsUri = "ws://echo.websocket.org/";
```
定義了一個WebSocket服務器的URI,以`ws://`開頭。另外還有一種以`wss://`開頭的URI,代表一個SSL加密的WebSocket URI。
```
websocket = new WebSocket(wsUri);
```
這行代碼創建了一個WebSocket對象。該對象具有`onopen`、`onclose`和`onmessage`事件,以及`send`和`close`方法,使用起來十分簡單。
WebSocket還需要服務器端的實現,即WebSocket服務器,它可以由HTTP服務器同時提供,參考這里了解更多: [https://developer.mozilla.org/en-US/docs/Web/API/WebSockets\_API/Writing\_WebSocket\_servers](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers)一般來說各主要編程語言都有自己的實現,我們只要選擇合適的即可。
更多關于WebSocket可參考:<https://en.wikipedia.org/wiki/WebSocket>
> 1. 來自于 <https://www.websocket.org/echo.html>[?](#reffn_1 "Jump back to footnote [1] in the text.")
- 前言
- 1 Web概述
- 1.1 什么是Web
- 1.2 超文本和超鏈接
- 1.3 URL
- 1.4 DNS
- 1.5 HTTP
- 1.5.1 客戶端請求
- 1.5.2 服務器應答
- 1.5.3 進一步了解HTTP
- 1.6 HTTPS
- 2 Web瀏覽器
- 2.1 HTML
- 2.1.1 文檔類型聲明
- 2.1.2 標簽和屬性
- 2.1.3 文檔結構
- 2.1.4 DOM
- 2.1.5 進一步了解HTML
- 2.2 CSS
- 2.2.1 樣式與樣式表
- 2.2.2 樣式表語法
- 2.2.3 級聯樣式表
- 2.2.4 進一步了解CSS
- 2.3 JavaScript
- 2.3.1 script標簽
- 2.3.2 操縱DOM
- 2.3.3 jQuery
- 2.3.4 進一步了解JavaScript
- 2.4 Ajax
- 2.5 移動設備與響應式Web設計
- 3 Web服務器
- 3.1 方法與資源
- 3.2 狀態代碼
- 3.3 靜態內容與動態內容
- 3.4 編程語言與技術
- 3.4.1 CGI
- 3.4.2 PHP
- 3.4.3 Java
- 3.4.4 Python
- 3.4.5 Ruby
- 3.4.6 Node.js
- 3.5 RESTful Web API
- 3.6 服務器架構
- 3.7 Web緩存
- 3.8 服務器推送
- 4 數據庫
- 4.1 關系型數據庫
- 4.2 NoSQL數據庫
- 5 Web服務器的其他組件
- 5.1 Cron
- 5.2 消息隊列
- 5.3 郵件服務器
- 6 開發工具與技術
- 6.1 Git
- 6.1.1 Git基礎操作
- 6.1.2 Git基本原理
- 6.1.3 進一步了解Git
- 6.2 敏捷開發