Netty构建WebSocket服务器(服务器端)

 

public class WSServer {
      public static void main(String[] args) throws Exception{
           
           EventLoopGroup mainGroup = new NioEventLoopGroup();
           EventLoopGroup subGroup = new NioEventLoopGroup();
           
           try {
                 ServerBootstrap server = new ServerBootstrap();
                 server.group(mainGroup, subGroup)
                      .channel(NioServerSocketChannel.class)
                      .childHandler(new WSServerInitializer());
                 
                 ChannelFuture future = server.bind(8088).sync();
                 
                 future.channel().closeFuture().sync();
           } finally {
                 mainGroup.shutdownGracefully();
                 subGroup.shutdownGracefully();
           }
           
      }
}

 

public class WSServerInitializer extends ChannelInitializer<SocketChannel>{
      @Override
      protected void initChannel(SocketChannel ch) throws Exception {
           ChannelPipeline pipeline = ch.pipeline();
           
           // websocket 基于http协议, 所以要有http编解码器
           pipeline.addLast(new HttpServerCodec());
           // 对写大数据流的支持
           pipeline.addLast(new ChunkedWriteHandler());
           // 对HttpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse
           // 几乎在netty中的编程都会使用到此handler
           pipeline.addLast(new HttpObjectAggregator(1024*64));
           
           //===============以上用于支持http协议===========================
           
           /**
            * websocket服务器处理的协议,用于指定给客户端连接访问的路由: /ws
            * 此handler会处理一些繁重复杂的事情
            * 握手: handshaking(close,ping,pong)
            * 对于websocket,都是以frames进行传输的,不同的数据类型对应的frames也不同
            */
           pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
           
           // 自定义handler

           pipeline.addLast(new ChatHandler());
      }
}

 

/**
 *
 * @author Edward
 * 处理消息的handler
 * TextWebSocketFrame:在netty中,是用于为websocket专门处理文本的对象,frame是消息的载体
 */

public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
      
      // 用于记录和管理所有客户端的channel
      private 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);
           
           for(Channel channel : clients) {
                 channel.writeAndFlush(
                            new TextWebSocketFrame("[服务器在]" + LocalDateTime.now() + "接收到的消息为:" + content));
           }
           // 与上面的for循环功能一致
//         clients.writeAndFlush(
//                    new TextWebSocketFrame("[服务器在]" + LocalDateTime.now() + "接收到的消息为:" + content));
      }
      /**
       *  当客户端连接服务端之后(打开连接)
       *  获取客户端的channel,并且放到ChannelGroup中进行管理
       */
      @Override
      public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
           clients.add(ctx.channel());
      }
      @Override
      public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
           // 当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel
           // clients.remove(ctx.channel());
           System.out.println("客户端断开,channel对应的长ID为:" + ctx.channel().id().asLongText());
           System.out.println("客户端断开,channel对应的短ID为:" + ctx.channel().id().asShortText());
      }
}

 

posted @ 2020-09-22 18:13  Edward_han  阅读(257)  评论(0编辑  收藏  举报