Netty Channel IO 事件拦截器, 自定义握手器 最佳实践

本文介绍如何使用 Netty 的 ChannelInterceptor 实现一个确认通信协议版本的握手器。通过示例代码展示了握手器的工作流程,包括如何拦截通道激活、读取事件及用户事件,并在验证版本后释放拦截器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

  接触过物联网的小伙伴都知道, 很多协议在正式通信前都需要进行握手这一操作, 如果握手失败将无法进行后续的业务通信.
例如在通信前可能需要确认设备型号, 协议版本, 元信息版本, 设备状态,地域信息等等, 这些都是必须在业务通信前要确认的.

  此文将展示如何通过Nettyx中的ChannelInterceptor来实现一个握手器, 注意千万别和Spring中的ChannelInterceptor搞混了!!
先引入依赖

请从maven中央仓获取{lastest.version},最新版本号
<dependency>
    <groupId>io.github.fbbzl</groupId>
    <artifactId>nettyx</artifactId>
    <version>{lastest.version}</version>
</dependency>

ChannelInterceptor

Nettyx提供了ChannelInterceptor这一工具
以下将展示如何实现一个简单的确认通信协议版本号的握手器
ChannelInterceptor默认会拦截所有IO事件直到调用free相关方法, 相反的, 如果调用reset方法将会重新开始拦截IO事件

// MyMessage为用户自行封装的业务消息实体, 本示例中仅作参考
@Slf4j
public class ProtocolVersionHandShaker extends ChannelInterceptor<MyMessage> {

	// 使用的协议版本
    private String usingVersion;

    @Override
    public void preChannelActive(ChannelHandlerContext ctx) {
    	// 如果是握手发起方, 需要在active中调用发起握手的请求消息
        // sendCheckProtocolVersionRequest(ctx);
        log.info("has send handshake req");
    }


    @Override
    protected void preChannelRead(ChannelHandlerContext ctx, MyMessage msg) throws Exception {
    	try {
    		String version = msg.getVersion();
    		if(version!=null && version.length()>0) {
    			this.usingVersion = msg.getVersion();
    			// 核心步骤, freeAndActive方法会将当前拦截器free掉, 后续此拦截器将不会参与消息解析
    			// 如果在free掉此拦截器之后, 后续又需要恢复此拦截器, 只需调用reset()方法即可
			    super.freeAndActive(ctx);
			}
		} catch(Exception unknown) {
     		// 如果是握手发起方的话, 出现异常可能会要进行重试, 重新发送版本核对请求
		     //sendCheckProtocolVersionRequest(ctx);
			 log.warn("protocol version check failed, response is [{}]", msg);
		}
    }

    @Override
    protected void preUserEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (ChannelEvents.isReadIdle(evt)) {
       	    log.info("intercepted channel read idle");
        }
    }

    @Override
    protected void preChannelReadComplete(ChannelHandlerContext ctx) {
        log.debug("intercepted channel read complete");
    }

==========================================================================

  如果后续需要重新恢复所有拦截器, 可以调用ChannelInterceptor.resetAll()恢复ChannelPipeline中所有拦截器.
  如果只需要恢复单个拦截器直接从ChannelPipeline中根据名字获取handler, 强转成ChannelInterceptor之后调用reset即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值