netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理、编码解码处理、收发数据方式》

作者: itstack

Netty开发中,客户端与服务端需要保持同样的;半包粘包处理,编码解码处理、收发数据方式,这样才能保证数据通信正常。

在前面NettyServer的章节中我们也同样处理了;半包粘包、编码解码等,为此在本章节我们可以把这些知识模块开发到NettyClient中。本章节涉及到的知识点有;LineBasedFrameDecoder、StringDecoder、StringEncoder、ChannelInboundHandlerAdapter等。

开发环境

  1. jdk1.8【jdk1.7以下只能部分支持netty】
  2. Netty4.1.36.Final【netty3.x 4.x 5每次的变化较大,接口类名也随着变化】
  3. telnet 测试【可以现在你的win7机器上测试这个命令,用于链接到服务端的测试命令】

代码示例

itstack-demo-netty-1-08
└── src
    ├── main
    │   └── java
    │       └── org.itstack.demo.netty.client
    │           ├── MyChannelInitializer.java
    │           ├── MyClientHandler.java
    │           └── NettyClient.java
    └── test
         └── java
             └── org.itstack.demo.netty.test
                 └── ApiTest.java

MyChannelInitializer.java

/**
 * 虫洞栈:https://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * Create by fuzhengwei on 2019
 */
public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        // 基于换行符号
        channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
        // 解码转String,注意调整自己的编码格式GBK、UTF-8
        channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
        // 解码转String,注意调整自己的编码格式GBK、UTF-8
        channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
        // 在管道中添加我们自己的接收数据实现方法
        channel.pipeline().addLast(new MyClientHandler());
    }
}

MyClientHandler.java

/**
 * 虫洞栈:https://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * Create by fuzhengwei on 2019
 */
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() + "\r\n";
        ctx.writeAndFlush(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);
        //通知客户端链消息发送成功
        String str = "客户端收到:" + new Date() + " " + msg + "\r\n";
        ctx.writeAndFlush(str);
    }
    /**
     * 抓住异常,当发生异常的时候,可以做一些相应的处理,比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常信息:\r\n" + cause.getMessage());
    }
}

NettyClient.java

/**
 * 虫洞栈:https://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * Create by fuzhengwei on 2019
 */
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("itstack-demo-netty client start done. {关注公众号:bugstack虫洞栈,获取源码}");
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            workerGroup.shutdownGracefully();
        }
    }
}

测试结果

启动模拟器NetAssist 设置TCP Server

启动客户端NettyClient

执行结果

/**
 * 虫洞栈:https://bugstack.cn
 * 公众号:bugstack虫洞栈  {获取学习源码}
 * Create by fuzhengwei on 2019
 */
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("itstack-demo-netty client start done. {关注公众号:bugstack虫洞栈,获取源码}");
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            workerGroup.shutdownGracefully();
        }
    }
}


上一篇:[netty案例,netty4.1基础入门篇七《嗨!NettyClient》]

下一篇:[netty案例,netty4.1基础入门篇九《自定义编码解码器,处理半包、粘包数据》]

微信搜索「bugstack虫洞栈」公众号,关注后回复「Netty专题案例」获取本文源码&更多原创专题案例!

文章列表

更多推荐

更多
  • Azure上Linux管理-十、使用 Azure Kubernetes 服务 技术要求,开始使用 AKS,与 Helm 一起工作,使用草稿,管理 Kubernetes,问题,进一步,使用 WSL 和 VS Code,安装依赖,kubectl 安装,使用 Azure CLI 创建集群,AKS 首次部署,创建服务,多
    Apache CN

  • Azure上Linux管理-十一、故障排除和监控您的工作负载 module(load="imuxsock"),技术要求,访问您的系统,Azure 日志分析,性能监控,问题,进一步,不允许远程访问,正在端口上工作,使用 nftables,引导诊断,Linux 登录,配置日志分析服务,安装 Azure
    Apache CN

  • Azure上Linux管理-十二、附录 第一章:探索微软 Azure 云,第二章:Azure 云入门,第三章:Linux 基础管理,第 4 章:管理 Azure,第五章:高级 Linux 管理,第七章:部署虚拟机,第八章:探索连续配置自动化,第 9 章:Azure 中的容器虚
    Apache CN

  • Azure上Linux管理-九、Azure 中的容器虚拟化 cloudconfig,集装箱技术导论,系统生成,Docker,Azure 容器实例,Buildah, Podman, and Skopeo,容器和储存,问题,进一步,容器历史,chroot 环境,OpenVZ,LXC,创建一个带启动的
    Apache CN

  • Azure上Linux管理-七、部署你的虚拟机 ResourceGroup 不存在,创建它:,vnet 不存在,创建 vnet,cloudconfig,Vagrant.config 结束,部署场景,Azure 中的自动部署选项,初始配置,流浪,封隔器,自定义虚拟机和 vhd,问题,进
    Apache CN

  • Azure上Linux管理-八、探索持续配置自动化 了解配置管理,使用 Ansible,使用地球形态,使用 PowerShell DSC,Azure 策略客户端配置,其他解决方案,问题,进一步,技术要求,Ansible 的安装,SSH 配置,裸最小配置,库存文件,Ansible 剧本和模
    Apache CN

  • Azure上Linux管理-五、高级 Linux 管理 技术要求,软件管理,网络,存储,systemd,问题,进一步,RPM 软件管理器,YUM 软件管理,基于 DNF 的软件管理,DPKG 软件管理器,运用 apt 进行软件管理,ZYpp 软件管理,识别网络接口,IP 地址识别,显示路由表
    Apache CN

  • Azure上Linux管理-六、管理 Linux 安全与身份 SELINUX=可以接受以下三个值之一:,permissiveSELinux 打印警告而不是强制执行。,disabled 没有加载 SELinux 策略。,SELINUXTYPE=可以接受以下三个值之一:,targeted 目标进程
    Apache CN

  • Azure上Linux管理-四、管理 Azure 使用 Azure CLI 和 PowerShell 管理 Azure 资源,技术要求,管理存储资源,管理网络资源,管理计算资源,虚拟机资源,问题,进一步,存储帐户,托管磁盘,Azure 文件,Azure Blob,虚拟网络,子网,网络安
    Apache CN

  • Azure上Linux管理-三、Linux 基础管理 Linux Shell,获取帮助,使用文本文件,在文件系统中找到你的方式,流程管理,自由访问控制,问题,执行命令,命令行编辑,与历史一起工作,自动完成,球状,重定向,处理变量,Bash 配置文件,使用手册页,使用信息文档,其他文档,文本
    Apache CN

  • 近期文章

    更多
    文章目录

      推荐作者

      更多