• 基于Netty的程序主动发送消息


    开发中希望基于netty开发的客户端可以既能在启动时与服务器通讯,又能在指定时间点或事件与服务器通讯,比如主动发送注销信息。

    1. 在启动时与服务器通讯可以在ChannelHandler的channleActive方法中实现。当客户端与服务端TCP链路建立成功时,Netty的NIO线程会调用channleActive方法,其中可以通过入参ChannelHandlerContext 的writeAndFlush方法发送指令给服务器。这一步是ChannelHandler 添加到ChannelPipeline 之后自动触发并接入ChannelHandlerContext参数的。

    2. 在指定时间点或事件与服务器通讯时,在函数里依然需要ChannelHandlerContext来发送指令,虽然没有程序可以传入该参数,但我们实际可以缓存ChannelHandlerContext,并直接使用。

    ChannelHandlerContext是在ChannelHandler 添加到 ChannelPipeline 时创建的一个实例,它代表了 ChannelHandler 和ChannelPipeline 之间的关联。接口ChannelHandlerContext 主要是对通过同一个 ChannelPipeline 关联的 ChannelHandler 之间的交互进行管理。ChannelHandlerContext 与 ChannelHandler 的关联从不改变,所以缓存它的引用是安全的。

    可以通过重写handlerAdded函数,缓存ChannelHandlerContext的引用。该函数在ChannelHandler 添加到 ChannelPipeline 时触发。

    代码如下

    public class ClientHandlerDemo extends ChannelDuplexHandler   {
        /**缓存ChannelHandlerContext*/
        private ChannelHandlerContext ctx;
        
        @Override
        /*添加到pipeline时自动触发*/
        public void handlerAdded(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }
        
        /**
         * 建立连接时
         */
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            logger.info("尝试建立连接时间:" + new Date());
            ctx.writeAndFlush(buildLogonMessage());
        }
        
        /**
         * 关闭连接时
         */
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            logger.info("Handler关闭连接。");
            super.channelInactive(ctx);
        }
    
        @Override
        public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
            logger.info("Handler关闭连接处理,时间:" + new Date());
            super.close(ctx, future);
        }
        
        /**主动关闭连接*/
        public void toClose() {
            if(ctx == null ) {
                logger.info("未建立连接。");
                return;
            }
            logger.info("发送注销消息,主动关闭连接。");
            ctx.channel().writeAndFlush(buildLogoutMessage()).addListener(ChannelFutureListener.CLOSE);
        }
    }

    参考

    https://www.w3cschool.cn/essential_netty_in_action/essential_netty_in_action-bj5a28bq.html

  • 相关阅读:
    SpringCloud Gateway使用实例
    Nacos服务注册与发现
    HashMap源码分析——put方法
    Volatile关键字——内存可见性
    Java的JIT编译器
    why spring?
    mysql 锁
    sql server 表变量和临时表
    mysql 存储过程
    mysql 截取字符串
  • 原文地址:https://www.cnblogs.com/zhaoshizi/p/13817496.html
Copyright © 2020-2023  润新知