| 日期 | 更新说明 |
|---|---|
| 2025年8月25日 | 初版发布 |
序言
寄黄几复 黄庭坚
我居北海君南海,寄雁传书谢不能。 桃李春风一杯酒,江湖夜雨十年灯。 持家但有四立壁,治病不蕲三折肱。 想见读书头已白,隔溪猿哭瘴溪藤。
我住在北方海滨,而你住在南方海滨,欲托鸿雁传书,它却飞不过衡阳。 当年春风里观赏桃李共饮美酒,江湖落魄,一别已是十年,常对着孤灯听着秋雨思念着你。 你支撑生计也只有四堵空墙,艰难至此;你治理国家就像三折肱的良医一样,不需要去请求别人的经验。 想你清贫自守发奋读书,如今头发已白了罢,隔着充满瘴气的山溪,猿猴哀鸣攀援深林里的青藤。
最近看韩跑跑接元婴去了,确实很感慨。其实韩天尊确实是凡人的映射。对于普通人来总有一种桃李春风一杯酒,江湖夜雨十年灯感觉,总是有种江湖一梦的惊愕。好看是好看,文章断更一周了;这篇文章本来是《服务器主动推送之SSE (Server-Sent Events)探讨》姊妹篇,迟迟没发布,今天终于要开始了。
概述
什么是WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
从上图可以看出 websocket 有两部分组成:
- 握手过程:这是从 HTTP 升级请求(Upgrade: websocket)到协议切换的“握手”过程
- 数据帧:数据传输基本结构,详细参考:www.openmymind.net/WebSocket-F…
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
以上图表摘自 RFC 6455 WebSocket 协议,描述了一个 WebSocket 帧的结构。
其他特点包括:
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 可以发送文本,也可以发送二进制数据。
- 没有同源限制,客户端可以与任意服务器通信。
- 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
ws://example.com:80/some/path
为什么选 WebSocket
WebSocket 的优点可以概括为:在需要高实时性、高频双向数据交换的场景下,它能提供一种延迟极低、开销更小、更高效的通信方案,从而显著提升用户体验并降低服务器负载。
其特点在《服务器主动推送之SSE (Server-Sent Events)探讨》也提到过,这里不赘述。
实践
JSR 356(Java API for WebSocket)
对于 Javaer 来说生态确实不错,JSF 针对websocket推出JSR 356(Java API for WebSocket)。JSR 356于2013年随Java EE 7发布,是首个官方WebSocket规范,旨在解决不同容器(如Tomcat、Jetty)的私有API差异问题,提供跨容器的统一开发接口。
核心组件与架构
1. 核心注解
@OnOpen:连接建立时触发,用于初始化会话。
@OnMessage:接收客户端消息,支持文本/二进制数据。
@OnClose:连接关闭时清理资源。
@OnError:处理通信异常
@ServerEndpoint:声明服务端端点,指定URI路径(如@ServerEndpoint("/chat"))
2. 核心对象
Session:代表一个WebSocket连接,用于发送消息、管理会话属性(如用户ID)。BasicRemote:同步发送消息(阻塞直至发送完成)。AsyncRemote:异步发送(非阻塞,适合高并发)BasicRemote:同步发送消息(阻塞直至发送完成)。
- EndpointConfig:配置端点参数(如子协议、扩展)。