netty实现websocket客户端与服务端消息透传

  • 前言:作为一个刚踏入职场的实习生 , 我很幸运参加了某个政府项目 , 并且在项目中负责一个核心模块功能的开发 , 而不是从头到尾对数据库的crud 。虽然我一直心里抱怨我的工作范围根本就不是实习生干的活 , 因为没有前辈带我、入职就开始改bug 。但在这样的环境下我却学到了很多东西 , 即便老板有压榨我的嫌疑 , 却给了我如此好的历练机会(但工资方面真的很亏QAQ) , 毕竟实习过后跳槽简历上还有亮点 。
  • 背景:在不同的网络环境、不同的开发语言组成的闭环系统中 , 多个模块之间要实时获取硬件设备的状态 , 并以xml报文的格式相互传递 。在必要的时候解析这个报文获取其中的关键信息完成相应的动作 , 最后直观地把信息显示给前端用户 。如此一来就是涉及到了跨终端通信 , 并且有的功能模块既要充当客户端分发指令 , 还要作为客户端从别处获取信息 。很不巧的是 , 我负责的模块正是充当消息中转站的作用 , 为了解决这个需求我才有了了解这种机制的机会 。
  • 正文:由于涉及到不同模块之间的通信 , 其中又包含了web前端 , 为了保持通信协议的一致性项目采用了ws协议 , 即websocket 。
http协议和ws协议:最直观的特点就是访问地址的写法上略有不同 , 两种访问分别为http://ip:port、ws://ip:port 。http协议访问采用一问一答的方式——客户端发起请求到服务端 , 服务端收到请求后返回对应的信息 , 通信结束 。虽然可以利用ajax发起异步的http请求 , 不过都是一次访问后连接就断开(ajax轮询可以解决此问题 , 对服务器资源消耗较大);ws协议建立于TCP协议之上 , 我们观察ws的头部信息会发现一件有意思的事情
HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0))GET / HTTP/1.1Host: localhost:8888Connection: UpgradePragma: no-cacheCache-Control: no-cacheUser-Agent: Mozilla/5.0 (windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/90.0.4430.212 Safari/537.36Upgrade: websocketOrigin: file://Sec-WebSocket-Version: 13Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9Sec-WebSocket-Key: RLnvly29Zl3sJQOfGFjO9w==Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bitscontent-length: 0websocket建立时是以http协议握手 , 当建立连接之后就不需要http之间双向通信 。协议深层次的东西以我目前的能力是无法理解的 , 将来有机会我会再回过头来分析底层协议 。那么接下来就进入我们的主题 。
引入maven依赖(结合项目实际情况而定):
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>5.0.0.Alpha2</version></dependency>我们的需求自己既是服务端向其他模块推送消息 , 又是客户端从别处获取消息后推送其他模块 。那么我们要在自己项目中集成netty客户端和服务端 , 因为客户端无法给多个连接推送消息 。这里我主要介绍
SimpleChannelInboundHandler类的三个方法:


    推荐阅读