从零学Netty(七)Netty实现 多人聊天室

£神魔★判官ぃ 2022-12-15 03:51 265阅读 0赞

实例demo

编写服务端

  1. /**
  2. * 服务端
  3. *
  4. * @author LionLi
  5. */
  6. public class GroupChatServer {
  7. private final int port;
  8. public GroupChatServer(int port) {
  9. this.port = port;
  10. }
  11. public void run() throws Exception {
  12. // boss组 使用一个线程接收和分发请求
  13. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  14. // worker工作组 默认线程数8 处理实际请求
  15. EventLoopGroup workerGroup = new NioEventLoopGroup();
  16. try {
  17. ServerBootstrap b = new ServerBootstrap();
  18. b.group(bossGroup, workerGroup)
  19. // 主线程处理类
  20. .channel(NioServerSocketChannel.class)
  21. // 针对主线程的配置 分配线程最大数量 128
  22. .option(ChannelOption.SO_BACKLOG, 128)
  23. // 针对子线程的配置 保持长连接
  24. .childOption(ChannelOption.SO_KEEPALIVE, true)
  25. // 子线程处理类
  26. .childHandler(new ChannelInitializer<SocketChannel>() {
  27. @Override
  28. protected void initChannel(SocketChannel ch) {
  29. ChannelPipeline pipeline = ch.pipeline();
  30. // 加入 编解码handler
  31. pipeline.addLast("decoder", new StringDecoder());
  32. pipeline.addLast("encoder", new StringEncoder());
  33. // 加入自己的业务处理handler
  34. pipeline.addLast(new GroupChatServerHandler());
  35. }
  36. });
  37. System.out.println("服务器正在监听......");
  38. ChannelFuture channelFuture = b.bind(port).sync();
  39. // 监听关闭
  40. channelFuture.channel().closeFuture().sync();
  41. } finally {
  42. bossGroup.shutdownGracefully();
  43. workerGroup.shutdownGracefully();
  44. }
  45. }
  46. public static void main(String[] args) throws Exception {
  47. new GroupChatServer(8088).run();
  48. }
  49. }

编写服务端业务处理器

  1. /**
  2. * 服务端业务处理器
  3. *
  4. * @author LionLi
  5. */
  6. public class GroupChatServerHandler extends SimpleChannelInboundHandler<String> {
  7. /**
  8. * 定义一个channle 组,管理所有的channel
  9. * GlobalEventExecutor.INSTANCE) 是全局的事件执行器,是一个单例
  10. * 内部使用ConcurrentHashMap管理,线程安全
  11. */
  12. private static final ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
  13. /**
  14. * 初始化连接事件
  15. */
  16. @Override
  17. public void handlerAdded(ChannelHandlerContext ctx) {
  18. Channel channel = ctx.channel();
  19. CHANNEL_GROUP.add(channel);
  20. }
  21. /**
  22. * 连接断开事件
  23. */
  24. @Override
  25. public void handlerRemoved(ChannelHandlerContext ctx) {
  26. System.out.println("聊天室人数:" + CHANNEL_GROUP.size());
  27. }
  28. /**
  29. * 通道新增事件
  30. */
  31. @Override
  32. public void channelActive(ChannelHandlerContext ctx) {
  33. System.out.println(ctx.channel().remoteAddress() + " 上线了");
  34. }
  35. /**
  36. * 通道关闭事件
  37. */
  38. @Override
  39. public void channelInactive(ChannelHandlerContext ctx) {
  40. System.out.println(ctx.channel().remoteAddress() + " 离线了");
  41. }
  42. /**
  43. * 读取数据
  44. */
  45. @Override
  46. protected void channelRead0(ChannelHandlerContext ctx, String msg) {
  47. CHANNEL_GROUP.writeAndFlush(msg);
  48. }
  49. /**
  50. * 异常事件
  51. */
  52. @Override
  53. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  54. //关闭通道
  55. ctx.close();
  56. }
  57. }

编写客户端

  1. /**
  2. * 客户端
  3. *
  4. * @author LionLi
  5. */
  6. public class GroupChatClient {
  7. private final String host;
  8. private final int port;
  9. private final String username;
  10. public GroupChatClient(String host, int port, String username) {
  11. this.host = host;
  12. this.port = port;
  13. this.username = username;
  14. }
  15. public void run() throws Exception {
  16. EventLoopGroup group = new NioEventLoopGroup();
  17. try {
  18. Bootstrap bootstrap = new Bootstrap()
  19. .group(group)
  20. .channel(NioSocketChannel.class)
  21. .handler(new ChannelInitializer<SocketChannel>() {
  22. @Override
  23. protected void initChannel(SocketChannel ch) {
  24. ChannelPipeline pipeline = ch.pipeline();
  25. //加入 编解码handler
  26. pipeline.addLast("decoder", new StringDecoder());
  27. pipeline.addLast("encoder", new StringEncoder());
  28. //加入自定义的handler
  29. pipeline.addLast(new GroupChatClientHandler());
  30. }
  31. });
  32. ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
  33. Channel channel = channelFuture.channel();
  34. channel.writeAndFlush(username + " 上线了");
  35. //客户端需要输入信息,创建一个扫描器
  36. Scanner scanner = new Scanner(System.in);
  37. while (scanner.hasNextLine()) {
  38. String msg = scanner.nextLine();
  39. if ("exit".equals(msg)) {
  40. channel.writeAndFlush(username + " 离开了");
  41. break;
  42. } else {
  43. channel.writeAndFlush(username + ":" + msg);
  44. }
  45. }
  46. } finally {
  47. group.shutdownGracefully();
  48. }
  49. }
  50. public static void main(String[] args) throws Exception {
  51. System.out.print("请输入用户名: ");
  52. Scanner scanner = new Scanner(System.in);
  53. String username = scanner.nextLine();
  54. new GroupChatClient("localhost", 8088, username).run();
  55. }
  56. }

编写客户端业务处理器

  1. /**
  2. * 客户端业务处理器
  3. *
  4. * @author LionLi
  5. */
  6. public class GroupChatClientHandler extends SimpleChannelInboundHandler<String> {
  7. /**
  8. * 读取数据
  9. */
  10. @Override
  11. protected void channelRead0(ChannelHandlerContext ctx, String msg) {
  12. System.out.println(msg.trim());
  13. }
  14. }

测试

  • 场景如下:
  • 启动服务端
  • 顺序启动客户端 群友ABC 并输入用户名
  • 分别打招呼
  • 倒序退出客户端 群友ABC

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70 1

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70 2

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70 3

项目已上传到gitee

地址: netty-demo

如果帮到您了,请帮忙点个star

发表评论

表情:
评论列表 (有 0 条评论,265人围观)

还没有评论,来说两句吧...

相关阅读