项目
一. linkmaster
1. websocket实现
使用netty实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ChannelPipeline pipeline = ch.pipeline(); // 因为使用http协议, 需要 http解码器 pipeline.addLast( new ChannelHandler[]{ new HttpServerCodec()}); // 以块方式写, 添加 chunkedWriter 处理器 pipeline.addLast( new ChannelHandler[]{ new ChunkedWriteHandler()}); /** * 说明: * 1. http数据在传输过程中是分段的,HttpObjectAggregator可以把多个段聚合起来; * 2. 这就是为什么当浏览器发送大量数据时,就会发出多次 http请求的原因 */ pipeline.addLast( new HttpObjectAggregator( 8192 )); /** * 说明: * 1. 对于 WebSocket,它的数据是以帧frame 的形式传递的; * 2. 可以看到 WebSocketFrame 下面有6个子类 * 3. 浏览器发送请求时: ws://localhost:7000/hello 表示请求的uri * 4. WebSocketServerProtocolHandler 核心功能是把 http协议升级为 ws 协议,保持长连接; * 是通过一个状态码 101 来切换的 */ pipeline.addLast( new WebSocketServerProtocolHandler( "/" )); //30 秒客户端没有向服务端发送心跳则关闭连接,后面是写,和读写 pipeline.addLast( new IdleStateHandler( 30 , 0 , 0 )); /** 心跳处理,如果触发了空闲Idle事件,就会处理。通过继承 ChannelInboundHandlerAdapter的userEventTriggered 实现,需要判断触发事件 evt instanceof IdleStateEvent 和 状态 event.state() == IdleState.READER_IDLE */ pipeline.addLast( new ChannelHandler[]{ new HeartBeatHandler( this .properties)}); /** 自定义消息处理器,继承SimpleChannelInboundHandler<WebSocketFrame> 的 channelRead0方法 需要判断消息是否为文本 WebSocketFrame frame instanceof TextWebSocketFrame */ pipeline.addLast( new ChannelHandler[]{ new TextMessageHandler()}); |
2.启动
通过实现ApplicationRunner接口run方法,处理初始化配置和启动,springboot启动后执行。
3.具体过程
客户端:
发送消息json格式,需要传clientId和type,type0握手,1心跳,2关闭连接,其他自定义
服务端:
通过类注解@MessageAccept,注册系统消息接收器。方法注解@type,定义0,1,2
不是系统消息,就实现默认的消息接收器DefaultMessageAcceptor,根据类型查找推送方式去推送
握手和心跳都是通过消息注册器注册,绑定clientId和channel的关系
ChannelRegistryImpl继承Observable,注册和删除时执行notifyObservers方法通知
NativeChannelMapping实现Observer接口,里面维护了concurrentHashMap维护clientId和channel的关系,执行update,判断新增还是删除
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步