【java入门到放弃】Netty实战
技术选择
HTTP和WebSocket是应用层协议。
TCP和UDP是传输层协议,
HTTP 是基于 TCP 运行的。
WebSocket 连接建立时基于 HTTP,建立成功后通信基于 TCP 上的 WebSocket 协议。
WebSocket:跨平台,简单接入,框架成熟
TCP 自定义协议:高吞吐、低延迟,可压缩消息,控制协议
WebSocket 控制帧
WebSocket 协议规定,除了文本和二进制消息,还有一些 控制帧 用于管理连接状态:
| 帧类型 | 说明 |
|---|---|
Ping |
心跳请求,客户端或服务器发起,期待对方返回 Pong |
Pong |
心跳响应,用于确认对方在线 |
Close |
关闭连接请求,可以携带状态码和原因 |
客户端和服务端都可能发送这三种控制帧
双方都发 Ping 的设计要谨慎或者避免
WebSocketServerProtocolHandler不会主动发 Ping。
握手阶段半包粘包
WebSocket连接Netty
WebSocket 有一个握手阶段(HTTP 阶段),握手成功后协议从 HTTP 切换成 WebSocket。
握手通常需要三个Handler配合完成
pipeline.addLast(new HttpServerCodec());//把 TCP 字节解析成 HTTP 消息
pipeline.addLast(new HttpObjectAggregator(65536));//把 HTTP 分片合并成完整请求
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));//处理 WebSocket 握手
HTTP 层(HttpServerCodec + HttpObjectAggregator)可以自己解决半包粘包问题。
HttpServerCodec类型是ChannelDuplexHandler,握手时,把 TCP 字节解析成 HTTP 消息。握手返回 101 Switching Protocols 时,它把 HttpResponse 编码回 TCP 字节发送给客户端。之后协议升级成 WebSocket 。所有 WebSocket 消息都是以 WebSocketFrame 形式在 pipeline 中传递。HttpServerCodec就不起作用了。HttpServerCodec 仍然可以用于发送普通 HTTP 响应,只是 WebSocket 消息时它不会再解析 TCP 数据。
HttpObjectAggregator类型是ChannelInboundHandlerAdapter,只处理入站 HTTP 消息,把分片合并成FullHttpRequest;出站消息不会被处理。
WebSocketServerProtocolHandler类型是ChannelInboundHandler, 握手阶段,处理入站消息,发送握手响应出站。握手完成后,负责把 TCP 字节解析成 WebSocketFrame、检查控制帧(Ping/Pong/Close)、自动处理关闭握手。负责把 WebSocketFrame 编码成 TCP 字节发送给客户端。
WebSocketServerProtocolHandler的出站作用是“转换器”,把 WebSocketFrame → TCP 字节”,而不是“拦截别人的出站消息”。
WebSocket阶段半包粘包
WebSocket 阶段的半包/粘包问题基本上都是由 WebSocketServerProtocolHandler内部的 WebSocketFrameDecoder解决的
关于心跳
在浏览器环境里:
不能发送 WebSocket 协议自带的 Ping 帧
这是 浏览器 WebSocket API 的限制,不是 Netty 的限制。
如果服务器发送的是 WebSocket 协议自带的 PingFrame,那么前端(浏览器)不需要写任何 pong 代码
浏览器会 自动返回 PongFrame。
更多推荐




所有评论(0)