WebSocket 由来已久, 经常使用于 "服务器推" 场景。最近开始学习 WebSocket (从 tomcat examples 开始), 本文的主要目的是作学习笔记, 同时记录一份开发指南。java
本文示例代码见: https://github.com/hanyong/exercise/tree/websocketgit
咱们先来看看 HTTP。angularjs
一次 HTTP 请求过程以下:github
客户端 | 服务器 | |
---|---|---|
1. | 客户端创建到服务器的 TCP 链接 | |
2. | 客户端发送请求 | |
3. | 客户端等待响应 | |
4. | 服务器收到请求 | |
5. | 服务器发送响应 | |
6. | 客户端收到响应 | |
7. | 请求结束 |
TCP 链接是支持双向同时读写的全双工协议, 可是咱们看传统的 HTTP 协议有几个问题:web
也就是说, 传统的 HTTP 1.0/1.1 协议没有充分利用 TCP 链接的能力.编程
HTTP 协议这样的设计主要是简化了编程模型, 想想传统的 CGI 脚本, 一个脚本只要可以接受输入, 产生输出, 就能够提供 web 服务。HTTP 协议缺乏 ISO 7 层网络模型中的会话层, 动态 web 应用使用 cookie 来保存会话信息。HTTP/1.1 默认开启长链接来优化性能, 但 HTTP 链接和请求依然是无状态的。对传统提供静态内容服务, 或返回信息相对肯定的 web 应用而言, 这样的设计并无问题, 或者说虽然有一些不足, 但尚能忍受。无状态的设计也简化了 HTTP 测试, 日志回放也成为重要的 HTTP 服务测试手段之一。api
直到 "服务器推" 场景的出现。服务器端信息随时可能变化, 咱们但愿将变化后最新的信息当即通知给客户端。传统的解决方案是客户端不断轮询服务器, 如每秒 1 次。这种轮询将产生许多额外的代价, 包括移动端流量收费, 而且编程模型也相对复杂。所以, 是时候开放 TCP 双向通讯的能力了。咱们能够从新写一个 TCP 服务器, 使用新的协议来通讯。但也许是为了复用 HTTP 的 80 端口, 依附现有 HTTP 生态圈, 让 web 应用平滑升级, websocket 基于 HTTP 协议设计, 顾名思义就是基于 web HTTP 协议, 释放原生 TCP socket 的能力。因此 websocket 一开始仍是按 HTTP 协议通讯, 随后才转换成 websocket。浏览器
一个 websocket 链接的创建过程以下:tomcat
客户端 | 服务器 | |
---|---|---|
1. | 客户端创建到服务器的 TCP 链接 | |
2. | 客户端请求将当前 TCP 链接用做 websocket | |
3. | 服务器收到请求, 赞成并确认将此 TCP 链接用做 websocket | |
4. | 客户端收到确认, HTTP 协议通讯结束 | |
5. | 双方使用 websocket 协议自由双向通讯 |
websocket 可基于 HTTP 创建, 即 ws
协议, 也可基于 HTTPS 创建, 即 wss
协议, 果真是复用了 HTTP 的基础设施。服务器
HTTP 客户端发送完请求后才会监听响应, 收到一次响应后即结束。常见的 HTTP 客户端有:
curl
, 如 curl localhost:8080/http
.浏览器 js 客户端, 如 angularjs 的 $http
服务.
$http.get("/http").then(function(resp) { vm.msg = resp.data; });
直接在浏览器输入 URL.
回顾 "服务器推" 场景, websocket 与 HTTP 协议最大的不一样在于服务器没必要等待请求, 也再也不使用 "请求", "响应" 这样的术语, 而改称为消息, 双方均可以随时互发消息。HTTP 客户端不会一直监听消息, 因此显然不能做为 websocket 客户端 (且不说协议是否兼容)。要使用 websocket, 客户端和服务器都须要改造。常见的 websocket 客户端有:
浏览器 js 客户端。感谢浏览器厂商, 如今的主流浏览器都支持 websocket 。
参考: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
var uri = "ws://" + window.location.host + "/ws"; vm.ws = new WebSocket(uri); vm.ws.onmessage = function(event) { vm.msg = event.data; $scope.$apply(); }
再来看服务端开发, java 定义了一套 javax.servlet-api
, 一个 HttpServlet
就是一个 HTTP 服务。java websocket 并不是基于 servlet-api 简单扩展, 而是新定义了一套 javax.websocket-api
。一个 websocket 服务对应一个 Endpoint
。与ServletContext
对应, websocket-api 也定义了 WebSocketContainer
, 而编程方式注册 websocket 的接口是继承自WebSocketContainer
的 ServerContainer
。一个 websocket 能够接受并管理多个链接, 所以可被视做一个 server
。主流 servlet 容器都支持 websocket, 如 tomcat, jetty 等。看 ServerContainer
api 文档, 可从 ServletContext
attribute 找到ServerContainer
。
阅读全文直接点击:http://click.aliyun.com/m/9971/