netty编程之使用protostuff作为数据传输载体

news2025/2/25 5:18:36

写在前面

源码 。
本文看下使用protostuff作为数据传输的载体。

1:正戏

1.1:server

server main:

package com.dahuyou.netty.protostuff.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {

    public static void main(String[] args) {
        new NettyServer().bing(7397);
    }

    private void bing(int port) {
        //配置服务端NIO线程组
        EventLoopGroup parentGroup = new NioEventLoopGroup(); //NioEventLoopGroup extends MultithreadEventLoopGroup Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(parentGroup, childGroup)
                    .channel(NioServerSocketChannel.class)    //非阻塞模式
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new MyChannelInitializer());
            ChannelFuture f = b.bind(port).sync();
            System.out.println("netty server start done. {}");
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }

    }

}

MyChannelInitializer:

package com.dahuyou.netty.protostuff.server;

import com.dahuyou.netty.protostuff.codec.ObjDecoder;
import com.dahuyou.netty.protostuff.codec.ObjEncoder;
import com.dahuyou.netty.protostuff.domain.MsgInfo;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) {
        //对象传输处理
        channel.pipeline().addLast(new ObjDecoder(MsgInfo.class));
        channel.pipeline().addLast(new ObjEncoder(MsgInfo.class));
        // 在管道中添加我们自己的接收数据实现方法
        channel.pipeline().addLast(new MyServerHandler());
    }

}

这里设置了自定义的protostuff的编解码器,如下:

package com.dahuyou.netty.protostuff.codec;

import com.dahuyou.netty.protostuff.util.SerializationUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class ObjEncoder extends MessageToByteEncoder {

    private Class<?> genericClass;

    public ObjEncoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Object in, ByteBuf out)  {
        if (genericClass.isInstance(in)) {
            byte[] data = SerializationUtil.serialize(in);
            out.writeInt(data.length);
            out.writeBytes(data);
        }
    }

}
package com.dahuyou.netty.protostuff.codec;

import com.dahuyou.netty.protostuff.util.SerializationUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;

public class ObjDecoder extends ByteToMessageDecoder {

    private Class<?> genericClass;

    public ObjDecoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() < 4) {
            return;
        }
        in.markReaderIndex();
        int dataLength = in.readInt();
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }
        byte[] data = new byte[dataLength];
        in.readBytes(data);
        out.add(SerializationUtil.deserialize(data, genericClass));
    }

}

消息处理类MyServerHandler:

package com.dahuyou.netty.protostuff.server;

import com.alibaba.fastjson.JSON;
import com.dahuyou.netty.protostuff.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户端主动链接服务端的链接后,这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.out.println("链接报告开始");
        /*System.out.println("链接报告信息:有一客户端链接到本服务端。channelId:" + channel.id());
        System.out.println("链接报告IP:" + channel.localAddress().getHostString());
        System.out.println("链接报告Port:" + channel.localAddress().getPort());
        System.out.println("链接报告完毕");*/
        //通知客户端链接建立成功
        String str = "通知客户端链接建立成功" + " " + new Date() + " " + channel.localAddress().getHostString() + "\r\n";
        ctx.writeAndFlush(MsgUtil.buildMsg(channel.id().toString(), str));
    }

    /**
     * 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端断开链接" + ctx.channel().localAddress().toString());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收msg消息{与上一章节相比,此处已经不需要自己进行解码}
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息类型:" + msg.getClass());
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息内容:" + JSON.toJSONString(msg));
    }

    /**
     * 抓住异常,当发生异常的时候,可以做一些相应的处理,比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常信息:\r\n" + cause.getMessage());
    }

}

1.2:client

client main:

package com.dahuyou.netty.protostuff.client;

import com.dahuyou.netty.protostuff.util.MsgUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {

    public static void main(String[] args) {
        new NettyClient().connect("127.0.0.1", 7397);
    }

    private void connect(String inetHost, int inetPort) {
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.AUTO_READ, true);
            b.handler(new MyChannelInitializer());
            ChannelFuture f = b.connect(inetHost, inetPort).sync();
            System.out.println("netty client start done. {}");

            f.channel().writeAndFlush(MsgUtil.buildMsg(f.channel().id().toString(),"你好,使用protobuf通信格式的服务端,我是大忽悠。"));
            f.channel().writeAndFlush(MsgUtil.buildMsg(f.channel().id().toString(),"你好,使用protobuf通信格式的服务端,我是大忽悠。"));

            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }

}

MyChannelInitializer:

package com.dahuyou.netty.protostuff.client;

import com.dahuyou.netty.protostuff.codec.ObjDecoder;
import com.dahuyou.netty.protostuff.codec.ObjEncoder;
import com.dahuyou.netty.protostuff.domain.MsgInfo;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        //对象传输处理
        channel.pipeline().addLast(new ObjDecoder(MsgInfo.class));
        channel.pipeline().addLast(new ObjEncoder(MsgInfo.class));
        // 在管道中添加我们自己的接收数据实现方法
        channel.pipeline().addLast(new MyClientHandler());
    }

}

protostuff的编解码器同server端的。
消息处理类MyClientHandler:

package com.dahuyou.netty.protostuff.client;

import com.alibaba.fastjson.JSON;
import com.dahuyou.netty.protostuff.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户端主动链接服务端的链接后,这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.out.println("链接报告开始");
        /*System.out.println("链接报告信息:本客户端链接到服务端。channelId:" + channel.id());
        System.out.println("链接报告IP:" + channel.localAddress().getHostString());
        System.out.println("链接报告Port:" + channel.localAddress().getPort());
        System.out.println("链接报告完毕");*/
        //通知客户端链接建立成功
        String str = "通知服务端链接建立成功" + " " + new Date() + " " + channel.localAddress().getHostString();
        ctx.writeAndFlush(MsgUtil.buildMsg(channel.id().toString(), str));
    }

    /**
     * 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("断开链接" + ctx.channel().localAddress().toString());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收msg消息{与上一章节相比,此处已经不需要自己进行解码}
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息类型:" + msg.getClass());
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息内容:" + JSON.toJSONString(msg));
    }

    /**
     * 抓住异常,当发生异常的时候,可以做一些相应的处理,比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常信息:\r\n" + cause.getMessage());
    }

}

1.3:测试

在这里插入图片描述
在这里插入图片描述
酱!!!

写在后面

参考文章列表

protostuff序列化方式学习 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2085479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这些持续高额派息的公司,都做对了什么?

2024年&#xff0c;资产荒已成共识&#xff0c;投资者梦寐以求寻找不怕火炼的“真金”。 受此影响&#xff0c;具有业绩高确定性和高股息的资产价值凸显。银河证券策略首席分析师杨超指出&#xff0c;当前&#xff0c;投资者对于现金回报的重视程度日益提升&#xff0c;促使上…

格行“信号增强技术”引领行业创新,格行随身WiFi带你感受不一样的速度与激情,行业第一的随身WiFi并非浪得虚名!

近年来&#xff0c;随着市场保有量的不断提升与相关技术的不断扩展&#xff0c;我国随身WiFi市场已经到了发展质量更高的“2.0”阶段&#xff0c;消费者对随身WiFi的需求变得多元且“高级”。与之对应的供给端&#xff0c;品牌之间的竞争也从未停止&#xff0c;有的品牌选择卷价…

微软Power Platform使用Power Automate低代码创建API接口供外部调用获取数据

微软Power Platform使用Power Automate低代码创建API接口供外部调用获取数据 在系统的使用过程中&#xff0c;有很多的情况需要外部调用内部数据增删改查&#xff0c;这里提供一种简单的方式&#xff0c;无需编写代码即可上手操作。 首先创建一个流&#xff0c;触发器为当收到…

区块链入门

1.1 区块链技术的发展 随着 2008 年比特币(Bitcoin) 的发明,一个被称为区块链(Blockchain) 的新概念进入了人们的视野,这项新技术据信有可能彻底改变整个社会。 区块链有望对每个行业产生颠覆的影响,包括但不限于 IT、金融、政府、媒体、医疗、法律和艺术等。一个流派将区…

飞利浦开放式耳机怎么样?南卡、飞利浦、Cleer、倍思一周横评

​作为一名有着四年耳机测评经验的耳机深度用户&#xff0c;最近切实感觉到开放式耳机这个品类是真的火了&#xff0c;不过也可以理解&#xff0c;开放式耳机的佩戴舒适度不是普通入耳式耳机可比的&#xff0c;而且更加健康卫生&#xff0c;在户外使用能够方便接收环境音&#…

有了这工具,再也不用死记硬背Linux命令了

前言 传统的终端工具往往需要用户记住大量的Linux命令。每当遇到不熟悉的命令时&#xff0c;就得花时间去查阅文档或在网上搜索&#xff0c;而且查到很多内容跟问题并不相关&#xff0c;这无疑降低了工作效率。 传统终端工具的痛点 在传统的Linux终端工具中&#xff0c;用户…

【掌握未来科技脉搏!电路仿真软件:数字电路学习的秘密武器】

在日新月异的科技时代&#xff0c;数字电路作为信息技术的基础&#xff0c;其重要性不言而喻。从简单的逻辑门电路到复杂的微处理器设计&#xff0c;数字电路的学习不仅关乎理论知识&#xff0c;更在于实践操作的掌握。而今&#xff0c;借助电路仿真软件这一强大工具&#xff0…

MS1861 宏晶微 视频显示与控制器芯片 提供开发资料

MS1861是一颗集成了HD、LVDS和数字视频信号输入的芯片。输出端可以驱动MIPI(DSI-2)、LVDS、Mini-LVDS以及TTL类型的TFT-LCD液晶显示。支持输入视频信号的滤波、图像增强、锐化、对比度调节、视频缩放、裁剪、旋转、内部字符&#xff08;图形&#xff09;叠加、帧频变化等处理。…

chapter09-项目——(房屋出租系统)——day11

目录 362-房屋出租需求 363-房屋出租设计 364-房屋出租工具类 365-房屋出租House类 366-房屋出租主菜单 367-房屋出租列表 368-房屋出租添加 369-房屋出租删除 370-房屋出租退出 371-房屋出租查找 372-房屋查找修改 362-房屋出租需求 363-房屋出租设计 364-房屋出租工…

错误: 找不到或无法加载主类 App.class,Java文件是怎么编译的

App.java文件: 文件路径:D:\com\fdw\App.java 文件内容: package com.fdw; public class App {public static void main(String[] args) {System.out.println("apple");} } 注意: App.java 必须放在com\fdw目录下(包名要和目录一致),否则无法启动! 编译

vrrp协议,主备路由器的选举

当VRRP备份组中的所有备份路由器&#xff08;BACKUP&#xff09;具有相同的优先级时&#xff0c;选举新的主路由器&#xff08;MASTER&#xff09;的过程将基于以下规则&#xff1a; IP地址优先&#xff1a;如果备份路由器的优先级相同&#xff0c;那么具有最高IP地址的路由器…

肉类快速鉴别仪

肉类快速鉴别仪是一种用于快速检测肉类中是否含有其他动物物种混合的仪器。它的功能主要包括以下几个方面&#xff1a; 动物物种鉴别&#xff1a;肉类快速鉴别仪可以快速识别肉类样本中的动物物种&#xff0c;例如牛肉、猪肉、羊肉等。通过分析肉类样本中的DNA或蛋白质序列&…

整理了100个Python精选库,建议收藏!

Python为啥这么火&#xff0c;这么多人学&#xff0c;就是因为简单好学&#xff0c;功能强大&#xff0c;整个社区非常活跃&#xff0c;资料很多。而且这语言涉及了方方面面&#xff0c;比如自动化测试&#xff0c;运维&#xff0c;爬虫&#xff0c;数据分析&#xff0c;机器学…

LLVM ERROR: Symbol not found: __svml_cosf8_ha问题解决

问题 python项目运行的时候会报错 LLVM ERROR: Symbol not found: __svml_cosf8_ha 解决方法 LLVM ERROR: Symbol not found: __svml_cosf8_ha 通常与 Intel 的数学库 SVML&#xff08;Sparse Vector Math Library&#xff09;有关。 SVML 是 Intel 提供的一个用于提高浮点数…

Python开源项目周排行 2024年第14周

#2024年第14周2024年8月16日1cursor一款功能强大的开源编程助手&#xff0c;利用大型语言模型&#xff08;LLM&#xff09;技术&#xff0c;通过交互帮助开发者完成代码补全、函数级代码生成等任务。Cursor不仅理解代码库&#xff0c;还能从中提取最匹配的代码&#xff0c;并引…

每天学习一个基础算法之顺序查找

目录 前言&#xff1a; 1、对顺序查找概念的诠释 2、顺序查找的使用场景 3、顺序查找的实现代码 顺序查找主体&#xff08;以接口函数的形式&#xff09; 测试部分&#xff08;主函数调用&#xff09; 调试结果 前言&#xff1a; 查找也是一种经常使用的算法&#xff0c;即根据…

机器学习/数据分析--通俗语言带你入门随机森林,并用随机森林进行天气分类预测(Accuracy为0.92)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 机器学习是深度学习和数据分析的基础&#xff0c;接下来将更新常见的机器学习算法及其案例注意&#xff1a;在打数学建模比赛中&#xff0c;机器学习用的…

心脑血管科曹启富医生:吃什么可以降低高血压

患者&#xff1a;曹医生&#xff0c;我家人有高血压&#xff0c;听说有些食物可以帮助降低血压&#xff0c;请问吃什么可以降低高血压呢&#xff1f; 曹医生说&#xff1a;您的问题非常实际&#xff0c;也是很多高血压患者和家属关心的问题。确实&#xff0c;通过合理的饮食调…

解决Springboot项目Maven下载依赖速度慢的问题

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

腾讯云Linux服务器运维,安装JDK、rabbitmq、nginx、Redis、ClickHouse

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; CODING 代码托管目录 1、…