学习Netty的第三天

it2026-09-27  13

学习Netty的第三天

不足之处聊天室服务器配置类服务器处理类 客户端客户端配置类客户端处理类 本章内容是观看《netty实战》书籍前7章,并且在B站重新找了一个学习视频,然后在观看部分课程后整理的。

不足之处

boosGroup 相当于一个组长 workerGroup相当于手下的员工 boosGroup将连接成功的通道分配给workerGroup

EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); ………… serverBootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,128)//分配任务队列 .childOption(ChannelOption.SO_KEEPALIVE,true) .handler(new LoggingHandler(LogLevel.INFO))// bossGroup 增加日志处理器

聊天室

服务器配置类

public class ChatServer { private int port; public ChatServer(int port) { this.port = port; } public void run() throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,128) .childOption(ChannelOption.SO_KEEPALIVE,true) .handler(new LoggingHandler(LogLevel.INFO))// bossGroup 增加日志处理器 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder",new StringDecoder());//解码器 pipeline.addLast("encoder",new StringEncoder());//编码器 //当满足该条件后,会传递个下一个handler 在userEventTiggered方法中处理 pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS)); pipeline.addLast("myServerHandler",new ChatServerHandler()); } }); ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); System.out.println("服务器启动完成"); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { new ChatServer(6888).run(); } }

服务器处理类

public class ChatServerHandler extends SimpleChannelInboundHandler<String> { //GlobalEventExecutor.INSTANCE 全局事件执行器 单例 private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //一旦连接 第一个被执行 //将当前channel 加入到组中 @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); //底层自动循环 channelGroup.writeAndFlush("客户端:" + channel.remoteAddress() + "加入聊天\n"); channelGroup.add(channel); } //断开连接 @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); //channelGroup.remove(channel) 当触发handlerRemoved 会自动去除当前channel channelGroup.writeAndFlush("客户端:" + channel.remoteAddress() + "离开聊天\n"); } //表示channel处于活动状态 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + "在"+simpleDateFormat.format(new Date())+"上线了\n"); } //表示channel不处于活动状态 @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + "在"+simpleDateFormat.format(new Date())+"离线了\n"); } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { final Channel channel = ctx.channel(); //根据不同身份 发送信息(自己) channelGroup.forEach(ch -> { if (channel != ch) {//不是当前的通道 ch.writeAndFlush("[客户]" + channel.remoteAddress() + "在"+simpleDateFormat.format(new Date())+"发送信息:" + msg+"\n"); }else{ ch.writeAndFlush("[自己]在"+simpleDateFormat.format(new Date())+"发送了消息:"+msg+"\n"); } }); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); cause.printStackTrace(); } /** * @Date: 2020/10/28 4:43 下午 * @Param: evt 事件 * @Param: ctx 上下文 * @Author: Lmy * @Description: */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if(evt instanceof IdleStateEvent){ IdleStateEvent event = (IdleStateEvent) evt; String eventType=null; switch (event.state()){ case READER_IDLE: eventType="读空闲"; break; case WRITER_IDLE: eventType="写空闲"; break; case ALL_IDLE: eventType="读写空闲"; break; } System.out.println(ctx.channel().remoteAddress()+"-->超时事件发生:"+eventType); } } }

客户端

客户端配置类

private final String host; private final int prot; public ChatClient(String host, int prot) { this.host = host; this.prot = prot; } private void run() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("encoder",new StringEncoder()); pipeline.addLast("decoder",new StringDecoder()); pipeline.addLast("myHandler",new ChatClientHandler()); } }); ChannelFuture channelFuture = bootstrap.connect(host, prot).sync(); Channel channel = channelFuture.channel(); System.out.println("————"+channel.localAddress()+"————"); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()){ String msg = scanner.nextLine(); channel.writeAndFlush(msg+"\r\n"); } } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { new ChatClient("127.0.0.1",6888).run(); }

客户端处理类

@Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(msg.trim()); }
最新回复(0)