Netty入门: 基于netty的websocket聊天室

项目结构

Netty入门: 基于netty的websocket聊天室_第1张图片

服务端

public class MyServer {
 public static void main(String[] args) throws Exception{
 // 负责连接的NioEventLoopGroup线程数为1
 EventLoopGroup bossGroup = new NioEventLoopGroup(1);
 EventLoopGroup wokerGroup = new NioEventLoopGroup();
​
 try{
 ServerBootstrap serverBootstrap = new ServerBootstrap();
 serverBootstrap.group(bossGroup,wokerGroup).channel(NioServerSocketChannel.class)
 // 加入日志
 .handler(new LoggingHandler(LogLevel.INFO))
 // 自定义channel初始化器
 .childHandler(new WebSocketChannelInitializer());
 // 绑定本机的8005端口
 ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8005)).sync();
 // 异步回调-关闭事件
 channelFuture.channel().closeFuture().sync();
 }finally {
 bossGroup.shutdownGracefully();
 wokerGroup.shutdownGracefully();
 }
​
 }

channel初始化器

public class WebSocketChannelInitializer extends ChannelInitializer {
 @Override
 protected void initChannel(SocketChannel ch) throws Exception {
 ChannelPipeline pipeline = ch.pipeline();
 //websocket协议本身是基于http协议的,所以这边也要使用http解编码器
 pipeline.addLast(new HttpServerCodec());
 //以块的方式来写的处理器
 pipeline.addLast(new ChunkedWriteHandler());
 //netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
 pipeline.addLast(new HttpObjectAggregator(8192));
​
 // 使用websocket协议
 //ws://server:port/context_path
 //参数指的是contex_path
 pipeline.addLast(new WebSocketServerProtocolHandler("/world"));
 //websocket定义了传递数据的中frame类型
 pipeline.addLast(new TextWebSocketFrameHandler());
 }
}

WebSocketChannelInitializerchannel初始化器

public class WebSocketChannelInitializer extends ChannelInitializer {
 @Override
 protected void initChannel(SocketChannel ch) throws Exception {
 ChannelPipeline pipeline = ch.pipeline();
 //websocket协议本身是基于http协议的,所以这边也要使用http解编码器
 pipeline.addLast(new HttpServerCodec());
 //以块的方式来写的处理器
 pipeline.addLast(new ChunkedWriteHandler());
 //netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
 pipeline.addLast(new HttpObjectAggregator(8192));
​
 // 使用websocket协议
 //ws://server:port/context_path
 //参数指的是contex_path
 pipeline.addLast(new WebSocketServerProtocolHandler("/world"));
 //websocket定义了传递数据的中frame类型,这里使用TextWebSocketFrame并自定义一个handler
 pipeline.addLast(new TextWebSocketFrameHandler());
 }
}
public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler {
 /**
 * 通道列表 用于存放通道
 */
 public static CopyOnWriteArrayList channelList = new CopyOnWriteArrayList();
​
 @Override
 protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
​
 /**
 * writeAndFlush接收的参数类型是Object类型,但是一般我们都是要传入管道中传输数据的类型,比如我们当前的demo
 * 传输的就是TextWebSocketFrame类型的数据
 */
 System.out.println(msg.text());
 // 遍历通道list,向非当前通道发送消息
 channelList.forEach(channel -> {
 if (channel != ctx.channel()){
 channel.writeAndFlush(new TextWebSocketFrame(ctx.channel().id().asShortText()+":" +msg.text()));
 }
 else {
 channel.writeAndFlush(new TextWebSocketFrame("我:" +msg.text()));
 }
 }
 );
 }
​
 /**
 * channel add后触发,向channelList添加新加入的通道
 *
 * @param ctx ctx
 * @throws Exception 异常
 */
 @Override
 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
 channelList.forEach(channel -> channel.writeAndFlush(new TextWebSocketFrame(ctx.channel().id().asShortText()+"上线了")));
 channelList.add(ctx.channel());
 }
​
 /**
 * channel连接断开时触发,猜测是TCP断开时触发回调 发送连接断开事件
 *
 * @param ctx ctx
 * @throws Exception 异常
 */
 @Override
 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
 channelList.forEach(channel -> channel.writeAndFlush(new TextWebSocketFrame(ctx.channel().id().asShortText()+"下线了")));
 }
​
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
 System.out.println("异常发生");
 ctx.close();
 }

Netty入门: 基于netty的websocket聊天室_第2张图片

TextWebSocketFrameHandler继承了SimpleChannelInboundHandler,SimpleChannelInboundHandler实际上是一个ChannelHandlerAdapter,其方法会在入站的时候被调用。这里我们通过重写handlerAdded方法,在通道创建后将其加入当channelList中,并向其余通道发送成员上线的提示信息。重写channelRead0方法,向所有非当前channel发送读取到消息。

前端




 
 WebSocket客户端



服务器输出:

测试

Netty入门: 基于netty的websocket聊天室_第3张图片

你可能感兴趣的:(netty)