谈谈SimpleChannelInboundHandler和使用中遇到的坑

在netty4.x中,handler作为netty中一个重要的组件,它通常被用来支持各种协议和处理数据的方式,处理各种事件。而ChannelInboundHandler是比较常用的handler,主要用来处理接收数据的一些事件,我们日常接收消息的处理都是通过扩展这个接口来自定义解析数据的。

ChannelInboundHandlerAdapter是ChannelInboundHandler它的一个简单实现,它的各种实现都只是将操作hannelPipeline中的下一个ChannelHandler中让链中的下一个ChannelHandler去处理。

SimpleChannelInboundHandler是一个支持泛型的消息处理的handler,继承自ChannelInboundHandlerAdapter,主要逻辑是重写了消息处理的方法channelRead,并新增加了channelRead0抽象方法提供给用户实现解码后的自定义处理代码如下:

 @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        boolean release = true;
        try {
            if (acceptInboundMessage(msg)) {
                @SuppressWarnings("unchecked")
                I imsg = (I) msg;
                channelRead0(ctx, imsg);
            } else {
                release = false;
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (autoRelease && release) {
                ReferenceCountUtil.release(msg);
            }
        }
    }

可以看到这个方法逻辑很简单,它会把默认当成你泛型的类型(I)来用,并调用自定义的逻辑channelRead0方法实现数据的处理,这里很坑的一点就是,你要在执行这个ChannelHandler之前,就要处理好msg的数据,比如如果实例化的时候指定泛型是String类型,可能在这个handler前面你就需要添加StringDecode解码,如果上面解码得到的不是String或者解码失败,这个方法则不会执行,关键它还不会报错,由于一些教程的例子里就用了这个类来接收处理String打印数据,我们把代码拷过来一运行就可能没有任何打印也没报错,然后就不知所措。这个时候就要去检查客户端编码和服务端的解码过程有没有问题了。

另外,网上还有一些教程说这个类处理完消息后会自动释放掉msg,其实这也是默认情况下会这样,看源码就知道,我们实例化这个类的时候指定autoRelease等于false,那么msg处理完成之后,就不会被释放掉,这时候调用提供的fire*方法传递给ChannelPipeline中的下一个ChannelHandler去走其他的逻辑是可以的,不过这个msg最终还是要自己释放掉哦.

 

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在C++,`read()`和`write()`是用于二进制数据读写的成员函数,可以用于从文件读取数据或将数据写入到文件。这两个函数是通过文件流对象调用的。 下面是关于`read()`和`write()`的一些重要信息: 1. `read()`函数定义:`istream& read(char* buffer, streamsize count);` `read()`函数用于从输入流读取二进制数据,并将其存储到指定的字符数组(buffer)。它接受两个参数:一个字符数组指针(buffer)和要读取的字节数(count)。 2. `write()`函数定义:`ostream& write(const char* buffer, streamsize count);` `write()`函数用于将指定的二进制数据写入到输出流。它接受两个参数:一个常量字符数组指针(buffer)和要写入的字节数(count)。 3. `read()`函数的返回值:`istream&` `read()`函数返回一个输入流对象的引用,可以用于链式调用其他输入操作。 4. `write()`函数的返回值:`ostream&` `write()`函数返回一个输出流对象的引用,可以用于链式调用其他输出操作。 下面是一个简单的示例,展示了如何使用`read()`和`write()`函数进行二进制数据的读写: ```cpp #include <iostream> #include <fstream> int main() { // 写入二进制数据 std::ofstream outfile("data.bin", std::ios::binary); // 创建输出文件流对象,并打开文件 if (outfile.is_open()) { int data[] = {1, 2, 3, 4, 5}; // 要写入的数据 int dataSize = sizeof(data); // 数据的字节数 outfile.write(reinterpret_cast<const char*>(data), dataSize); // 将数据写入文件 outfile.close(); // 关闭文件 } else { std::cerr << "Failed to open the file." << std::endl; } // 读取二进制数据 std::ifstream infile("data.bin", std::ios::binary); // 创建输入文件流对象,并打开文件 if (infile.is_open()) { const int bufferSize = 5 * sizeof(int); // 缓冲区大小 char buffer[bufferSize]; // 缓冲区 infile.read(buffer, bufferSize); // 从文件读取数据到缓冲区 int* data = reinterpret_cast<int*>(buffer); // 将字符数组转换为整数数组 for (int i = 0; i < bufferSize / sizeof(int); i++) { // 输出读取的数据 std::cout << data[i] << " "; } std::cout << std::endl; infile.close(); // 关闭文件 } else { std::cerr << "Failed to open the file." << std::endl; } return 0; } ``` 在上述代码,首先使用`std::ofstream`对象创建输出文件流对象,并以二进制模式打开名为"data.bin"的文件。然后,我们创建一个整数数组`data`并将其写入到文件使用`write()`函数将数据写入文件。 接下来,我们使用`std::ifstream`对象创建输入文件流对象,并以二进制模式打开同样的文件。我们创建一个字符数组缓冲区`buffer`,并使用`read()`函数从文件读取数据到缓冲区。 然后,我们将字符数组缓冲区转换为整数数组`data`,并遍历输出读取的数据。 通过使用`read()`和`write()`函数,我们可以在C++进行二进制数据的读写操作,以实现更灵活和高效的数据处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值