netty学习—实现websocket长连接和socket之间通信
最近正在学习netty,跟着教程写了一个基于WebSocket的网页聊天室,对netty有了一定的了解,现在正好项目使用到长连接,选用了netty。
项目目标:客户端A(网页)和服务端通过WebSocket进行通信,客户端B和服务端通过Socket通信,把客户端B的数据传输到客户端A,桥梁为服务端
Socket服务端监听8090端口,长连接服务端监听8089端口,客户端A连接到8089端口,客户端B连接到8090端口
由于是需要对两个端口数据进行不同处理,所以我们创建两个
ServerBootstrap
,分别绑定两个端口,一个ServerGzhBootstrap
处理客户端B和服务端的socket通信;ServerWxQBootstrap
处理客户端A和服务端之间的WebSocket长连接通信
ServerInitializer
,实现ChannelInitializer
,负责初始化客户端B和服务端通信的处理器HandlerWebSocketChannelInitializer
,实现ChannelInitializer
,负责初始化客户端A和服务端长连接通信的处理器HandlerServerInitializer
添加一个自定义SimpleChannelInboundHandler
负责处理客户端B和服务端socket通信WebSocketChannelInitializer
添加一个自定义SimpleChannelInboundHandler
负责处理客户端A和服务端WebSocket长连接通信
网页聊天室作为客户端A,客户端B通过Socket通信并接收控制台的输入作为通信数据传递给服务端,服务端再传递给客户端A
问题:
netty中SimpleChannelInboundHandler类的泛型中指定了传入的消息的类型,只能接收这种类型的消息,客户端B发送的String类型消息与客户端A接收的TextWebSocketFrame类型不同,客户端A无法接收。
解决方法:
我们把客户端B发送的String类型消息在Socket服务端接收到,要将其发送给客户端A(需要将其封装成TextWebSocketFrame类型才能发送给客户端A),而且我们就必须要有客户端A的channel,我们才可以调用writeAndFlush
方法把数据写入客户端A
使用什么可以得到客户端A的channel呢?
那就是ChannelGroup
,我们定义一个类保存全部Channel客户端作为全局ChannelGroup,每次有客户端Channel创建(handlerAdded
方法),我们就把它保存到该全局ChannelGroup中,每次channel使用完毕,ChannelGroup会为我们自动删除其中无用的channel,这样我们就可以获取所有的客户端channel