十一、WebSocket 协议开发应用
WebSocket 是 HTML5 开始提供的一种浏览器与服务端进行全双工通信的网络技术,WebSocket 于2011年被 IETF 定为标准 RFC6455,WebSocket API 被W3C定为标准。
WebSocket 的特点:
- 单一的TCP连接,采用全双工模式通信;
- 对代理,防火墙和路由器透明;
- 无头部信息、Cookie 和身份验证;
- 无安全开销;
- 通过
ping/pong
帧保持链路激活; - 服务器可以主动传消息给客户端,不再客户端需要轮询。
11.2、 WebSocket入门
WebSocket 设计出来的目的就是要取代轮询和Comet技术,使客户端浏览器具备像C/S 架构下的桌面系统一样实时通信的能力。
WebSocket 本质是就是一个TCP 连接,在数据传输的稳定性和数据量大小方面,和轮询以及Comet技术相比,具体很大的性能优势。
11.2.1、WebSocket 连接建立
建立WebSocket 连接时,需要通过客户端或浏览器向服务端发出握手请求。为建立一个 WebSocket 连接,客户端首先需要向服务器发起一个HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息Upgrade:WebSocket
表明这是一个申请协议升级的 HTTP 请求。如下图
请求消息中的 Sec-WebSocket-Key
是随机的,服务器会用这些数据来构造出一个 SHA-1的信息摘要,把 Sec-WebSocket-Key
加上一个魔幻字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
,使用 SHA-1 加密,然后进行 BASE-64 编码,将结果作为 Sec-WebSocket-Accept
头的值,返回给客户端。服务端应答如下:
11.2.2、WebSocket 生命周期
握手成功后,客户端和服务端就可以通过message
的方式进行通信了,一个消息可以有一个或多个帧组成,WebSocket 的消息不一定对应一个特定网络层的帧,它可以被分割成多个帧或被合并。
11.2.3、WebSocket 连接关闭
为关闭 WebSocket 连接,客户端和服务端需要一个安全的方法关闭底层TCP 连接和 TLS回话。如果合适,丢弃任何可能已经接收的字节,必要时(受到攻击)可以通过任何手段关闭连接。
底层 TCP 连接,在正常情况下,应首先由服务器关闭。异常情况下,可由客户端发起 TCP Close,因此,当服务器被指示关闭 WebSocket 连接时,它应立即发起一个TCP Close 操作,客户端应该等待服务器的 TCP Close 。
11.3、Netty WebSocket 协议开发
Netty 基于 HTTP 协议栈开发了 WebSocket 协议栈,利用 Netty 的 WebSocket 的协议栈可以非常方便的开发出 WebSocket 的服务端和客户端。
下面将通过一个小例程来实现 Netty WebSocket 的客户端和服务端的开发,其主要功能为:客户端发送消息到服务端,服务端对请求消息进行判断,如果是合法的 WebSocket 消息,则响应返回 Netty WebSocket 服务端消息以及时间。
11.3.1、WebSocket 服务端开发
利用Netty 开发WebSocket 服务端的关键是网络 I/O 事件处理器handler,其中在 handler 处理的事件有:
- 判断区分 HTTP请求和 WebSocke 请求,因为第一次请求握手消息是由HTTP 协议承载;
- 如果是 HTTP 握手请求,则根据通过握手工厂类
WebSocketServerHandshakerFactory
创建握手处理类WebSocketServerHandshaker
实例;其中握手处理了中的handshake
方法会将 websocket的编辑码类动态的添加到 ChannelPipeline - 链路建立成功后,客户端提交文本到服务端,服务端分别判断,是否是关闭连接、是否为 ping 指令消息,是否是支持的文本消息,然后做出响应,返回给客户端。
代码如下:
1 | public class WebSocketServer { |
运行效果如下
11.4、Netty UDP 协议开发
用户数据报协议(User Datagram Protocol,UDP)是一种传输层协议。在 TCP/IP 网络中,它与 TCP 协议一样用于处理数据包,是一种无连接的协议。
TCP 协议在进行数据传输时,需要建立连接,并且每次传输的数据都需要进行确认。当不再进行传输数据时,还需要断开连接。这样做虽然安全,但是效率较低。而 UDP 协议正好避免了这些过程,它是一种没有复杂控制,提供面向无连接的通信服务协议。
UDP 协议具备以下特点:
- 没有各种连接:在传输数据前不需要建立连接,也避免了后续的断开连接。
- 不重新排序:对到达顺序混乱的数据包不进行重新排序。
- 没有确认:发送数据包无须等待对方确认。因此,使用 UDP 协议可以随时发送数据,但无法保证数据能否成功被目标主机接收。
11.4.1、UDP 服务端开发
1 | public class NettyUdpServer { |
11.4.2、UDP 客户端开发
1 | public class NettyUdpClient { |
十二、私有协议栈开发
广义上区分,通信协议可以分为共有协议和私有协议。由于私有协议的灵活性,和时候在公司或者组织内部使用,按需定制,升级方便,灵活性好。
绝大多数私有协议传输层基于TCP/IP,利用 Netty 的 NIO TCP 协议栈可以非常方便地进行私有协议的定制和开发。