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

概要

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

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

确保使用最新版本nettyx,此处为了演示使用了如下版本
<dependency>
    <groupId>io.github.fbbzl</groupId>
    <artifactId>nettyx</artifactId>
    <version>2.2.22-RELEASE</version>
</dependency>

ChannelInterceptor

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

@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");
    }

	// msg 为用户自行封装的消息实体, 本示例中仅作参考
    @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");
    }

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值