netty源码分析(二十五)Netty自定义协议与TCP粘包拆包问题解决之道

2023-05-16

上一节说了TCP的粘包和拆包,用一个实例的方式做了说明,那么在netty里面是怎么解决粘包和拆包问题呢,这就需要编解码器,我们写一个简单的自动以协议的demo,说明一下编解码器在解决tcp粘包和拆包的解决方式。
先罗列一下服务端的代码:
MyServer负责服务端的启动:

public class MyServer {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new MyServerInitializer());
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();
        }finally{
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

MyServerInitializer 负责加入编解码器和handler,包括我们自己定义的编解码器(MyPersonDecoder、MyPersonEncoder):

public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
       ChannelPipeline channelPipeline =  ch.pipeline();
        channelPipeline.addLast(new MyPersonDecoder());
        channelPipeline.addLast(new MyPersonEncoder());
        channelPipeline.addLast(new MyServerHandler());
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

MyServerHandler,接受客户端发来的信息并打印调用次数,之后向客户端写入一个uuid:

public class MyServerHandler extends SimpleChannelInboundHandler<PersonProtocal> {
    private int count;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, PersonProtocal msg) throws Exception {
        System.out.println("服务端接受到的数据:");
        System.out.println("数据长度:"+msg.getLength());
        System.out.println("数据内容:"+ new String(msg.getContent(), Charset.forName("utf-8")) );
        System.out.println("服务端接收到的消息数量:"+(++count));

        String responseMessage = UUID.randomUUID().toString();
        int responseLength = responseMessage.getBytes(Charset.forName("utf-8")).length;
        byte[] responseContent = responseMessage.getBytes(Charset.forName("utf-8"));
        PersonProtocal personProtocal = new PersonProtocal();
        personProtocal.setLength(responseLength);
        personProtocal.setContent(responseContent);
        ctx.writeAndFlush(personProtocal);

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

解码器,将字节数组解码成我们自定义的协议PersonProtocal类型:

public class MyPersonDecoder extends ReplayingDecoder<Void> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("MyPersonDecoder decode invoked ");
        int length = in.readInt();
        byte[] content = new byte[length];
        in.readBytes(content);

        PersonProtocal personProtocal = new PersonProtocal();
        personProtocal.setLength(length);
        personProtocal.setContent(content);

        out.add(personProtocal);
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

PersonProtocal 自定义的协议的封装,其实很简单,只有消息的长度和消息内容,先读取消息长度,再读取消息内容:

public class PersonProtocal {
    private int length;

    private byte[] content;

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

解码器MyPersonDecoder ,我们继承了ReplayingDecoder无需关注粘包问题,将字节转换为协议实体(PersonProtocal):

public class MyPersonDecoder extends ReplayingDecoder<Void> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("MyPersonDecoder decode invoked ");
        int length = in.readInt();
        byte[] content = new byte[length];
        in.readBytes(content);

        PersonProtocal personProtocal = new PersonProtocal();
        personProtocal.setLength(length);
        personProtocal.setContent(content);

        out.add(personProtocal);
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

编码器MyPersonEncoder实现很简单,这是将数据(PersonProtocal)写入到网络:


public class MyPersonEncoder extends MessageToByteEncoder<PersonProtocal> {

    @Override
    protected void encode(ChannelHandlerContext ctx, PersonProtocal msg, ByteBuf out) throws Exception {
        System.out.println("MyPersonEncoder encode invoked");
        out.writeInt(msg.getLength());
        out.writeBytes(msg.getContent());
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最后是客户端的程序MyClientHandler,启动的时候向服务端发送十条消息,再者接受服务端回执的uuid:

public class MyClientHandler extends SimpleChannelInboundHandler<PersonProtocal> {

    private int count;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for(int i=0;i<10;i++){
            String messaage = "sent from client";
            int length = messaage.getBytes(Charset.forName("utf-8")).length;
            byte[] content = messaage.getBytes(Charset.forName("utf-8"));
            PersonProtocal personProtocal = new PersonProtocal();
            personProtocal.setLength(length);
            personProtocal.setContent(content);
            ctx.writeAndFlush(personProtocal);
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, PersonProtocal msg) throws Exception {
        int length = msg.getLength();
        byte[] content = msg.getContent();
        System.out.println("客户端接收到的消息");
        System.out.println("长度:"+length);
        System.out.println("消息内容:"+new String(content,Charset.forName("utf-8")));
        System.out.println("客户端接收到的消息数量:"+(++this.count));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

客户端启动程序Myclient:

public class Myclient {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {

                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline channelPipeline =  ch.pipeline();
                    channelPipeline.addLast(new MyPersonDecoder());
                    channelPipeline.addLast(new MyPersonEncoder());
                    channelPipeline.addLast(new MyClientHandler());
                }
            });
            ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
            channelFuture.channel().writeAndFlush("hello");
            channelFuture.channel().closeFuture().sync();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

整个流程:
客户端启动之后,向服务端发送了十条“sent from client”客户端经过编码器MyPersonEncoder发送出去, 然后服务端接收到之后先经过解码器MyPersonDecoder,解码成PersonProtocal实体,然后打印消息内容,服务端每接收到一条“sent from client”,紧接着向客户端发送一个uuid(讲过编码器MyPersonEncoder),之后客户端收到uuid,经过解码器MyPersonDecoder转换成PersonProtocal实体。
服务端打印结果:

MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:1
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:2
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:3
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:4
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:5
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:6
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:7
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:8
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:9
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
服务端接受到的数据:
数据长度:16
数据内容:sent from client
服务端接收到的消息数量:10
MyPersonEncoder encode invoked
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

客户端打印结果:

MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonEncoder encode invoked
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:aeb03767-5b48-4c1b-ae08-2c643fa511f1
客户端接收到的消息数量:1
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:22a19d24-3a53-4954-af51-6d8a47a31412
客户端接收到的消息数量:2
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:0bb4cbff-8725-4aa1-b431-81d185639dd0
客户端接收到的消息数量:3
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:4770c9ec-8868-4253-a6be-632105bc677c
客户端接收到的消息数量:4
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:07562dc9-bde7-42bf-91b5-a964d320a4ab
客户端接收到的消息数量:5
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:08955003-5487-47a4-92c0-3fd6d636abbd
客户端接收到的消息数量:6
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:4e35d4d9-5780-46df-a78a-8bc0bf293e03
客户端接收到的消息数量:7
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:051d7e80-8e1c-4b0a-979e-9ab390c9d139
客户端接收到的消息数量:8
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:a220680e-852f-4525-9ec4-06f7912dcabe
客户端接收到的消息数量:9
MyPersonDecoder decode invoked 
客户端接收到的消息
长度:36
消息内容:64bf6571-e246-4f4e-89f5-afe609ccc4ed
客户端接收到的消息数量:10

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

netty源码分析(二十五)Netty自定义协议与TCP粘包拆包问题解决之道 的相关文章

  • 基于docker搭建mysql,redis,mongo,gitlab,wiki等开发环境

    今天基于docker搭建一整套开发环境 首先安装docker yum y install docker io 使用加速器 xff1a vim etc docker daemon json 添加163的加速地址 xff1a 34 regist
  • Android编译系统分析五:system.img的生成过程

    Android编译系统分析系列文章 xff1a android编译系统分析 xff08 一 xff09 source build envsetup sh与lunch Android编译系统 xff08 二 xff09 mm编译单个模块 an
  • linux学习笔记--Xshell远程登陆linux

    1 登录xshell官网XSHELL NetSarang Website xff0c 输入姓名和邮箱 xff0c 下载免费版的Xshell xff0c 下载链接会发送到邮箱中 下载完成后直接安装即可 2 双击打开安装完成的Xshell xf
  • Apache使用localhost可以访问但使用本机IP(局域网)不能访问

    Apache使用localhost可以访问但使用本机IP 局域网 不能访问 Apache 使用localhost 127 0 0 1 可以访问 xff0c 使用本机IP 局域网 不能访问 xff0c 为什么本机ip地址不能访问localho
  • ubuntu14.04LTS命令行安装xfce4桌面

    安装ubuntu14 04LTS后 xff0c 需要一个桌面 xff0c 因此选择安装xfce4 1 安装 1 1 安装默认版本4 10 sudo apt get install xfce4 1 2 安装版本4 12 1 sudo add
  • OCLint的部分规则(Convention 部分)

    OCLint的部分规则 xff08 Convention 部分 xff09 对OCLint的部分规则进行简单翻译解释 xff0c 有部分进行了验证以及进一步分析 测试 OCLint其他相关内容如下 xff1a OCLint iOS OC项目
  • 修改virualbox下的虚拟系统Ubuntu的内存

    VBoxManage exe在VirtualBox 安装目录下 xff0c 如下图 xff0c 我们进VirtualBox 安装目录查看到VBoxManage exe 要使用这个工具 xff0c 就先了解一下这个工具吧 xff0c 要用命令
  • 四旋翼定高篇之惯导加速度+速度+位置三阶互补融合方案

    笔者最近正在做四旋翼惯性导航的部分 xff0c 利用加速度计进行速度估计 位置估计 xff0c 从而实现四旋翼的垂直方向上的定高 水平方向上的定点控制 首先在这里引用学长之前参考APM飞控里面互补滤波惯导融合方案 xff1a 原文见四旋翼位
  • 从APM源码分析GPS、气压计惯导融合

    最近事多 xff0c 忙着开源自研飞控 xff0c 现主要工作基本已经完成 xff0c 代码最迟下月中旬开放 xff0c 博客来不及更新 xff0c 还请各位见谅 xff0c 后面会抽空多更的咯 xff01 xff01 xff01 自研飞控
  • Angular 展示标签内容,而不是标签本身

    在angualr项目的html页面中 xff0c 如果展示的数据包含html标签 xff0c 则不会被解析 xff0c 而是原样展示标签 xff0c 比如 lt br gt xff0c 而不会产生换行的效果 xff0c 解决办法是 xff0
  • 安装ROS过程中的rosdep init 和 rosdep update 命令执行不成功的解决办法

    一 解决 rosdep init 命令执行不成功 xff1a 不成功信息 xff1a RROR cannot download default sources list from https raw githubusercontent co
  • ubuntu如何开启22端口支持ssh访问

    1 查看本机IP ifconfig 执行后如果提示服务不存在 xff0c 则需要下载该工具 sudo apt install net tools 2 查看端口22是否被占用 netstat nltp grep 22 n 不以进程的服务名称
  • 算法 - 剑指Offer 二叉搜索树的第k大节点

    题目 给定一棵二叉搜索树 xff0c 请找出其中第 k 大的节点的值 解题思路 这题比较简单 xff0c 首先题目中说需要倒数第几大的数字 xff0c 第一反应就是这个坑定是一个倒序数组 xff0c 然后去找 xff0c 然后我们可以知道的
  • 解决Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?

    运行项目有时候在dialog这里一直报错 xff0c 按照日志在网上找解决方案 很多都跑到了底层去解决这问题 然而我不懂底层 xff0c 没办法 继续找咯 苍天明鉴 xff01 找到问题了 原因一般是展示dialog的时候用的是异步 xff
  • 程序员生涯之生活篇

    作为一名非正规的程序员菜鸟 xff0c 我没有什么职场沉淀 xff0c 也没有开阔的视野 xff0c 只是读了几篇博文与时讯 xff0c 有所感触 xff0c 想要记录一下自己的想法与体会 xff0c 暂定为程序员生涯之生活篇 首先介绍一下
  • 【Kubernetes系列】私有仓库Harbor和Registry的安装使用

    目录 一 Harbor 简介二 Registry 简介三 Harbor 和 Registry 比较四 Harbor 的安装使用1 环境要求 xff08 1 xff09 硬件要求 xff08 2 xff09 软件要求 2 环境准备 xff08
  • Ping过程 原理 详解

    如果你想了解PING的原理 xff0c 就看我的文章 xff0c 不要去网上找 xff0c 找不到什么好的内容 看了我文章 xff0c 也许你会从对网络一窍不通 xff0c 到豁然开朗 先看拓朴图 xff1a 我在这里讲拼的两情况 一种是同
  • java怎么去除字符串中的数字。。。

    比如 xff1a str 61 123assume345contribute 把数字去掉 str 61 assumecontribute public class Hello public static void main String a
  • FFplay源码分析-EOF

    本系列 以 ffmpeg4 2 源码为准 xff0c 下载地址 xff1a 链接 xff1a 百度网盘 提取码 xff1a g3k8 FFplay 源码分析系列以一条简单的命令开始 xff0c ffplay i a mp4 a mp4下载链
  • ubuntu离线安装软件及依赖

    因为工作站不能联网 xff0c 所以需要离线下载相应的安装包来安装 Linux中的安装包有个问题 xff1a 一个包可能有很多个依赖 在联网条件下 xff0c 会直接下载相应的依赖 xff0c 但是在离线条件下 xff0c 如何确保依赖下载

随机推荐

  • Ubuntu16.04 获取并启用root账户的方法

    1 打开终端 xff0c 输入 xff1a sudo passwd root xff0c 然后更改root密码 2 输入 xff1a su root xff0c 是否可以进入root用户 xff0c 如果出现前面root 64 用户名 xf
  • AngularJs与ReactJS优缺点&适用场景

    Angular的优缺点 xff1a 优点 AngularJS是一套完整的框架 xff0c angular有自带的数据绑定 render渲染 angularUI库 过滤器 directive 模板 服务 q defer http xff0c
  • Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'inform

    Expression 1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 39 information schema PROFIL
  • rabbitmq的消息持久化处理开启,再关闭后,消费者启动报错

    今天在测试rabbitmq的消息持久化处理时 xff0c 一切顺利 xff0c 可是再想测试ACK消息确认机制时 xff0c 消费者却无法启动了 xff0c 报如下错误 xff1a org springframework amqp rabb
  • VMware下Linux无法播放声音的解决方案

    问题背景 宿主机环境 xff1a Windows 10 VMware Workstation版本 xff1a VMware Workstation 12 VMware Workstation 15 客户机环境 xff1a CentOS 7
  • pip更新及Requirement already up-to-date解决方法

    pip更新及Requirement already up to date解决方法 文 xff1a 铁乐与猫 2018 9 11 更新命令 将pip更新到最新版本 python m pip install upgrade pip Anacon
  • 如何高效的使用适配器Adapter

    如何高效的使用适配器Adapter 当我们在使用ListView GridView时 xff0c 都会给其设置相应的适配器 xff0c 用来给其设置数据 xff0c 会去继承BaseAdapter xff0c 重写getCount getI
  • kotlin 没有@Parcelable注解

    在使用kotlin的时候 xff0c 有的时候需要对实体类进行序列化的操作 序列化的方式就两种 xff0c 一种是Serializable xff0c 一种是Parcelable 在android中 xff0c 基本都是使用的Parcela
  • Android studio3.0+ 编译Lame库(CMake方式)

    最近在学习音视频方面的知识 xff0c 购买了音视频开发进阶指南 xff0c 在交叉编译LAME库的时候 xff0c 书中使用的还是旧版本的编译方式 xff0c 现在android studio在2 2以后就开始使用CMake的编译方式了
  • 打印正整数n拆分的所有情况

    题目 xff1a 把一个正整数n拆分成若干个正整数的相加 xff0c 列出所有组合 例如 xff1a 4 61 4 4 61 1 43 3 61 2 43 2 4 61 1 43 1 43 2 4 61 1 43 1 43 1 43 1 动
  • redis实现积分排行榜

    在项目开发中常常遇到一些积分排行的问题 一个典型的积分行榜包括以下常见功能 xff1a 能够记录每个用户的分数 xff1b 能够对用户的分数进行更新 xff1b 能够查询每个用户的分数和名次 xff1b 能够按名次查询排名前N名的用户 xf
  • 如何减小Ubuntu 16.04系统下VMware虚拟机硬盘空间占用过大问题

    VMware虚拟机占用硬盘空间只增大不减少 xff0c 即使你删除文件 xff0c 占用的硬盘空间也不释放 用了一段时间后空间不够了 解决办法 方法一 在vmware的安装目录下 xff0c 有一个vmware vdiskmanager 关
  • 使用Redis实现积分排行榜,并支持同积分按时间排序

    排行榜这个功能很常见 xff0c 多用于激励用户活跃和拉新 xff0c 比如CSDN平台实现的周榜 xff0c 按照每周文章总阅读量进行排名 xff0c 用排名和奖品激励用户持续在平台上输出高质量内容 最近笔者也做了一个积分排行榜的功能 x
  • 神奇的排序

    代码 xff1a 此方法只能对互不相同的正整数排序 xff0c 也成为神奇的排序 xff0c 从编程珠玑中看到的 public class magicSort public static void main String args TODO
  • 学会自己测天气之 起卦篇

    找三个一元的硬币 xff0c 找一个安静的没人的地方 xff0c 把钱合在掌内反复摇动 xff0c 心中反复问神灵你想问的事情 然后抛出硬币 xff0c 记录反面 xff08 有花的那面 xff09 的数量 xff08 总共有四种情况 xf
  • Java 使用 jdbc 连接 mysql

    首先要下载Connector J地址 xff1a http www mysql com downloads connector j 这是MySQL官方提供的连接方式 xff1a 解压后得到jar库文件 xff0c 需要在工程中导入该库文件
  • 找零钱的方案数以及所需最少张数的钞票的方案

    问题描述 xff1a 我们知道人民币有1元 xff0c 2元 xff0c 5元 xff0c 10元 xff0c 20元 xff0c 50元 xff0c 100元这几种表示 xff0c 现在给你一个整数 n 让你找零 xff0c 求出有多少种
  • 2017京东校招编程题 烽火台

    描述 xff1a n 个 烽火台围成一个圈 xff0c 任意两个烽火台只要中间的烽火台比他们两个都低就能看见彼此 xff0c 当然相邻的肯定能看见对面 xff0c 求能看见彼此的对数 输入 5 烽火台的个数 3 2 5 4 1 烽火台的高地
  • 利用Oh-My-Zsh打造你的超级终端

    什么是Zsh Zsh是一款强大的虚拟终端 xff0c 既是一个系统的虚拟终端 xff0c 也可以作为一个脚本语言的交互解析器 Zsh的一些特性 兼容bash xff0c 原来使用bash的兄弟切换过来毫无压力 强大的历史纪录功能 xff0c
  • netty源码分析(二十五)Netty自定义协议与TCP粘包拆包问题解决之道

    上一节说了TCP的粘包和拆包 xff0c 用一个实例的方式做了说明 xff0c 那么在netty里面是怎么解决粘包和拆包问题呢 xff0c 这就需要编解码器 xff0c 我们写一个简单的自动以协议的demo xff0c 说明一下编解码器在解