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和服务端通信的处理器Handler
WebSocketChannelInitializer,实现ChannelInitializer,负责初始化客户端A和服务端长连接通信的处理器Handler
ServerInitializer添加一个自定义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
任何获取到客户端A的channel?
客户端A和客户端B很大一个区别就是端口号,我们可以通过端口号来判断是客户端A还是客户端B
全局ChannelGroup
public class GlobalChannelGroup {
public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
}
服务端
服务端启动器
public class Server {
public static void main(String[] args) throws InterruptedException { <