18.Netty-WebSocket编码实战
基础组件:3.Netty全局入口Bootstrap · 5.Netty的EventLoop · 6.Netty的ChannelPipeline · 7.Netty的ChannelHandler与Context
1. 启动类
public static void main(String[] args) throws InterruptedException {
//主从线程池
// 主接收客户端连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//Netty启动类 装线程进去
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
//设置Nio的双向通道
.channel(NioServerSocketChannel.class)
//workergroup的处理器
.childHandler(new WSServerInitializer());
//绑定端口,[同步]等待成功
ChannelFuture channelFuture = bootstrap.bind(10086).sync();
//监听关闭的Channel
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
2. 初始化器
public class WSServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
//通过Channel获取管道
ChannelPipeline pipeline = channel.pipeline();
//通过管道 添加 Handler处理器 http的编解码处理器
// websocket 基于http
pipeline.addLast("HttpServerCodec", new HttpServerCodec());
//添加对大数据流的支持
pipeline.addLast(new ChunkedWriteHandler());
// 对HttpMessage进行聚合,聚合为FullHttpResponse或FullHttpRequest
// 几乎在netty的编程中,都会使用它
pipeline.addLast(new HttpObjectAggregator(1024 * 64));
//上面是http相关的 下面是WebSocket相关的
//此handler会处理一些复杂的繁重的操作
//会处理一些握手的操作:handshaking(opening handshake,closing handshake,ping,pong)
//对于WebSocket来说,数据都是以frames的形式传递的,不同的数据类型对应不同的frame
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
//自定义处理器
pipeline.addLast(new ChatHandler());
}
}
3. 聊天 handler
/**
- 自定义助手类
- SimpleChannelInboundHandler 对于请求来说,等于入站
- TextWebSocketFrame 用于websocket专门处理的文本数据对象,Frame是消息的载体
*/
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
//客户端传输的消息
String content = msg.text();
System.out.println("客户端传输的消息:" + content);
Channel channel = ctx.channel();
String currentLongChannelId = channel.id().asLongText();
String currentShortChannelId = channel.id().asShortText();
System.out.println("channelId:" + currentLongChannelId + "short:" + currentShortChannelId);
//需要用Frame去传递
channel.writeAndFlush(new TextWebSocketFrame("服务器时间" + System.currentTimeMillis()));
}
}