服务器推送技术与websocket协议

websocket 作为现代浏览器的长连接标准,可以很好的解决浏览器与服务器实时通讯的问题,那么在 websocket 出现之前是怎么解决这个问题的呢?首先来回顾一下在此之前浏览器和服务器的”长连接”之路。

回顾

在 websocket 协议出来之前,主要是有三种方向去实现类似 websocket 的功能的。

Flash

flash 支持 socket 通讯功能,基于 flash 可以很简单的实现与服务器建立通讯。

  • 优点:开发简单、兼容性高
  • 缺点:需要浏览器启用 flash 功能,并且逐渐被浏览器淘汰

AJAX Polling

浏览器使用 ajax 去轮询服务器,服务器有内容就返回,轮询也分为短轮询和长轮询。

短轮询

短轮询即浏览器通过 ajax 按照一定时间的间隔去请求服务器,服务器会立即响应,不管有没有可用数据。

  • 流程图:
  • 优点:短链接、服务器处理方便。
  • 缺点:实时性低、很多无效请求、性能开销大

长轮询

长短轮询则是浏览器通过 ajax 与服务器建立连接,服务器在没有数据返回时一直阻塞着,直到有数据之后才返回响应。

  • 流程图:
  • 优点:实时性高
  • 缺点:每个连接只能返回一次数据

COMET

comet 也是常用的一种服务器推送技术,主要的原理是通过 HTTP Chunked 响应,将消息源源不断的推送给浏览器,通常情况下服务器返回的响应内容都是定长的,会使用 Content-Length 来指定响应报文的长度,而 Chunked 编码的响应则是通过一种特殊的编码,只要浏览器没有遇到结束标识,就会边解析边执行对应的响应内容。

  • chunked 编码报文示例:
<code>HTTP/1.1 200 OK
Content-Type: text/html
Date: Thu, 08 Aug 2019 02:50:06 GMT
Transfer-Encoding: chunked

11
callback('data1')
11
callback('data2')
0
/<code>

报文格式为:

<code>\r\n
\r\n
\r\n
\r\n
...
0\r\n
/<code>

由 16 进制的数字来标识一个 chunk data 数据的长度,在读取到 0\r\n 时结束,通过一直读取 chunk data 来执行 js 代码,从而向客户端推送数据。

  • go 语言实现:
<code>func main() {
	http.HandleFunc("/push", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		flusher := w.(http.Flusher)
		w.Write([]byte(" "))
		flusher.Flush()
		// 延迟一秒,以便观察浏览器的边解析边执行
		time.Sleep(time.Second)
		w.Write([]byte(" "))
		flusher.Flush()
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}
/<code>

通过 iframe 实现

iframe 实现是通过隐藏一个 ,通过 iframe 连接到服务器,服务器响应带有


分享到:


相關文章: