netty Force-closing a channel whose registration task was not accepted by an event loop问题

我这边第一次连接netty可以,但是关闭netty连接以后,再次使用连接就会报这个错,其实很简单的问题,但是一下子蒙住了,搞了半天,后来发现是全局变量的问题,

我把下面这两行代码放入了全局变量里,重启系统第一次连接没问题,关闭连接第二次开启连接就出现报错 Force-closing a channel whose registration task was not accepted by an event loop 连接不上。

 EventLoopGroup parentGroup = new NioEventLoopGroup();
 //负责网络的读写
 EventLoopGroup childGroup = new NioEventLoopGroup();

因为我还得需要通过接口关闭连接,针对上面问题我是这样改的

定义一个安全线程的hashmap用来存储EventLoopGroup 对象,在关闭资源方法里通过map取出来进行关闭,就不会出现这个问题了

@Component
public class NettyServer {
    private static Logger logger = LoggerFactory.getLogger(NettyServer.class);

    private ConcurrentHashMap mapEventLoopGroup = new ConcurrentHashMap();

    private Channel channel;

    // 开启连接
    public ChannelFuture bing(InetSocketAddress address) {
        // 配置服务端NIO线程组-负责接收客户端的连接
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        //负责网络的读写
        EventLoopGroup childGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        ChannelFuture channelFuture = null;
        System.out.println("进入bind方法");
        try {
            // 添加boss和worker组
            b.group(parentGroup, childGroup)
                    // 非阻塞模式
                    .channel(NioServerSocketChannel.class)
                    // 设置TCP的缓冲区
                    .option(ChannelOption.SO_BACKLOG, 128)
                    // 增加接收缓冲区
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(4096))
                    // childHandler 去绑定具体的事件处理器
                    .childHandler(new ChannelInit());
            // 绑定端口
            channelFuture = b.bind(address).syncUninterruptibly();
            System.out.println("绑定端口");
            System.out.println(channelFuture);
            channel = channelFuture.channel();
            System.out.println(channel);
            mapEventLoopGroup.put("parent", parentGroup);
            mapEventLoopGroup.put("child", childGroup);
        } catch (Exception e) {
            // 优雅退出,释放线程池资源
            System.out.println("进入catch方法");
            e.printStackTrace();
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        } finally {
            if (null != channelFuture && channelFuture.isSuccess()) {
                logger.info("netty服务启动完成!");
            } else {
                logger.error("netty服务启动失败!");
            }
        }
        return channelFuture;
    }

    // 关闭连接
    public boolean destroy() {
        try {
            if (null == channel) {
                return false;
            } else {
                channel.close();
                channel = null;
                System.out.println("关闭channel");
            }
            if (mapEventLoopGroup.containsKey("parent")) {
                EventLoopGroup parentGroup = (EventLoopGroup) mapEventLoopGroup.get("parent");
                parentGroup.shutdownGracefully();
                System.out.println("关闭parent");
                mapEventLoopGroup.remove("parent");
            }
            if (mapEventLoopGroup.containsKey("child")) {
                EventLoopGroup child = (EventLoopGroup) mapEventLoopGroup.get("child");
                child.shutdownGracefully();
                System.out.println("关闭child");
                mapEventLoopGroup.remove("child");
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    public Channel getChannel() {
        return channel;
    }

    /*
     * @Author df
     * @Description 发送消息
     * @Date 15:28 2021/1/14
     **/
    public AjaxResult sendMessage(byte[] byteData, String orderNo) {
        System.out.println("进入发送message方法(),命令号是:" + orderNo);
        System.out.println(ServerHandler.ctxMaps.size());
        try {
            // 指定不同的连接请求发送命令
            for (Map<String, ChannelHandlerContext> ctxMap : ServerHandler.ctxMaps) {
                if (ctxMap.containsKey(orderNo)) {
                    ChannelHandlerContext ctx = ctxMap.get(orderNo);
                    if (ctx == null) {
                        return AjaxResult.error("请确保打开TCP连接操作!");
                    }
                    // netty需要转换ByteBuf才可使用
                    ByteBuf bytebuf = Unpooled.buffer();
                    bytebuf.writeBytes(byteData);
                    ServerHandler.isAccess = true;
                    ctx.writeAndFlush(bytebuf);
                    String ip = IpCabinetBind.findOrderNoByIp(orderNo);
                    String msg = "给Ip为:" + ip + "发送了命令号是" + orderNo + "指令";
                    System.out.println(msg);
                    Session session = WebSocketServer.sessionPools.get("android");
                    if (session != null) {
                        boolean isSucc = WebSocketServer.sendMessage(session, msg);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            ServerHandler.isAccess = false;
            return AjaxResult.error("服务器报错!发送指令失败!");
        }
        return null;
    }
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值