首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

WebSocket 协议(1)

WebSocket 协议(1)

1.1 背景知识由于历史原因,在创建一个具有双向通信机制的 web 应用程序时,需要利用到 HTTP 轮询的方式。围绕轮询产生了 “短轮询” 和 “长轮询”。
短轮询浏览器赋予了脚本网络通信的编程接口 XMLHttpRequest,以及定时器接口 setTimeout。因此,客户端脚本可以每隔一段时间就主动的向服务器发起请求,询问是否有新的信息产生:
  • 客户端向服务器发起一个请求,询问 “有新信息了吗”
  • 服务端接收到客户端的请求,但是此时没有新的信息产生,于是直接回复 “没有”,并关闭链接
  • 客户端知道了没有新的信息产生,那么就暂时什么都不做
  • 间隔 5 秒钟之后,再次从步骤 1 开始循环执行
长轮询使用短轮询的方式有一个缺点,由于客户端并不知道服务器端何时会产生新的消息,因此它只有每隔一段时间不停的向服务器询问 “有新信息了吗”。而长轮询的工作方式可以是这样:
  • 客户端向服务器发起一个请求,询问 “有新信息了吗”
  • 服务器接收到客户端的请求,此时并没有新的信息产生,不过服务器保持这个链接,像是告诉客户端 “稍等”。于是直到有了新的信息产生,服务端将新的信息返回给客户端。
  • 客户端接收到消息之后显示出来,并再次由步骤 1 开始循环执行
可以看到 “长轮询” 相较于 “短轮询” 可以减少大量无用的请求,并且客户端接收到新消息的时机将会有可能提前。
继续改进我们知道 HTTP 协议在开发的时候,并不是为了双向通信程序准备的,起初的 web 的工作方式只是 “请求-返回” 就够了。
但是由于人们需要提高 web 应用程序的用户体验,以及 web 技术本身的便捷性 - 不需要另外的安装软件,使得浏览器也需要为脚本提供一个双向通信的功能,比如在浏览器中做一个 IM(Instant Message)应用或者游戏。
通过 “长、短轮询” 模拟的双向通信,有几个显而易见的缺点:
  • 每次的请求,都有大量的重复信息,比如大量重复的 HTTP 头。
  • 即使 “长轮询” 相较 “短轮询” 而言使得新信息到达客户端的及时性可能会有所提高,但是仍有很大的延迟,因为一条长连接结束之后,服务器端积累的新信息要等到下一次客户端和其建立链接时才能传递出去。
  • 对于开发人员而言,这种模拟的方式是难于调试的
于是,需要一种可以在 “浏览器-服务器” 模型中,提供简单易用的双向通信机制的技术,而肩负这个任务的,就是 WebSocket
1.2 协议概览协议分为两部分:“握手” 和 “数据传输”。
客户端发出的握手信息类似:
1
2
3
4
5
6
7
8
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13




服务端回应的握手信息类式:
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Sec-WebSocket-Protocol: chat
客户端的握手请求由 请求行(Request-Line) 开始。客户端的回应由 状态行(Status-Line) 开始。请求行和状态行的生产式见  首行之后的部分,都是没有顺序要求的 HTTP Headers。其中的一些 HTTP头 的意思稍后将会介绍,不过也可包括例子中没有提及的头信息,比如 Cookies 信息,见  。HTTP头的格式以及解析方式见  

一旦客户端和服务端都发送了它们的握手信息,握手过程就完成了,随后就开始数据传输部分。因为这是一个双向的通信,所以客户端和服务端都可以首先发出信息。
在数据传输时,客户端和服务器都使用 “消息 Message” 的概念去表示一个个数据单元,而消息又由一个个 “帧 frame” 组成。这里的帧并不是对应到具体的网络层上的帧。
一个帧有一个与之相关的类型。属于同一个消息的每个帧都有相同的数据类型。粗略的说,有文本类型(以 UTF-8 编码  )和二进制类型(可以表示图片或者其他应用程序所需的类型),控制帧(不是传递具体的应用程序数据,而是表示一个协议级别的指令或者信号)。协议中定义了 6 中帧类型,并且保留了 10 种类型为了以后的使用。
返回列表