netty 拆包和粘包 (三)

在tcp编程底层都有拆包和粘包的机制

  拆包

    当发送数据量过大时数据量会分多次发送

   以前面helloWord代码为例

    

复制代码
package com.liqiang.nettyTest2;

public class nettyMain {
    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                Server server = new Server(8081);
                server.start();
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Client client1=new Client("127.0.0.1", 8081);
                client1.connection();
                client1.sendMsg("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. His book w"  
                        + "ill give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the process "  
                        + "of configuring and connecting all of Netty’s components to bring your learned about threading models in ge"  
                        + "neral and Netty’s threading model in particular, whose performance and consistency advantages we discuss"  
                        + "ed in detail In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. Hi"  
                        + "s book will give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the"  
                        + " process of configuring and connecting all of Netty’s components to bring your learned about threading "  
                        + "models in general and Netty’s threading model in particular, whose performance and consistency advantag"  
                        + "es we discussed in detailIn this chapter you general, we recommend Java Concurrency in Practice by Bri"  
                        + "an Goetz. His book will give We’ve reached an exciting point—in the next chapter;the counter is: 1 2222"  
                        + "sdsa ddasd asdsadas dsadasdas");
            }
        }).start();
    }
}
复制代码

打印

可以发现这里拆分成了2次发送

  粘包

    当发送数据量过小时会组合成一次发送

复制代码
package com.liqiang.nettyTest2;

public class nettyMain {
    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                Server server = new Server(8081);
                server.start();
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Client client1=new Client("127.0.0.1", 8081);
                client1.connection();
                for(int i=0;i<100;i++) {
                    client1.sendMsg("d");
                }
                
                
            }
        }).start();
    }
}
复制代码

可以发现有时多条发送的数据会组合成一条发送

解决方案

netty提供了解码器来解决拆包和粘包的问题

LineBasedFrameDecoder 

通过换行符来区分包

服务器端增加LineBasedFrameDecoder

复制代码
package com.liqiang.nettyTest2;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.AsciiHeadersEncoder.NewlineType;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    private Server server;
    public ServerChannelInitializer(Server server) {
        this.server=server;
    }
    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        // TODO Auto-generated method stub
        channel.pipeline()
        .addLast(new LineBasedFrameDecoder(2048))//2048是限制一个包的最大字节数。如果超过将会报异常
        .addLast("decoder",new StringDecoder())//接收到数据 自动将将buffer转换为String 避免自己再转
        .addLast("encoder",new StringEncoder())//发送数据 可以直接发送String 框架内部转换为buffer传输
        .addLast(new ServerHandle(server));
    }

}
复制代码

客户端

复制代码
package com.liqiang.nettyTest2;

public class nettyMain {
    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                Server server = new Server(8081);
                server.start();

            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Client client1=new Client("127.0.0.1", 8081);
                client1.connection();
                client1.sendMsg("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. His book w"  
                        + "ill give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the process "  
                        + "of configuring and connecting all of Netty’s components to bring your learned about threading models in ge"  
                        + "neral and Netty’s threading model in particular, whose performance and consistency advantages we discuss"  
                        + "ed in detail In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. Hi"  
                        + "s book will give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the"  
                        + " process of configuring and connecting all of Netty’s components to bring your learned about threading "  
                        + "models in general and Netty’s threading model in particular, whose performance and consistency advantag"  
                        + "es we discussed in detailIn this chapter you general, we recommend Java Concurrency in Practice by Bri"  
                        + "an Goetz. His book will give We’ve reached an exciting point—in the next chapter;the counter is: 1 2222"  
                        + "sdsa ddasd asdsadas dsadasdas"+System.getProperty("line.separator"));//System.getProperty("line.separator") 兼容linux和windows换行符的区别
            }
        }).start();
    }
}
复制代码

如果发送数据忘记拼换行符 服务器将不会有任何打印

 

DelimiterBasedFrameDecoder

通过指定符号区分

服务器端

复制代码
package com.liqiang.nettyTest2;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.AsciiHeadersEncoder.NewlineType;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    private Server server;
    public ServerChannelInitializer(Server server) {
        this.server=server;
    }
    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        // TODO Auto-generated method stub
        channel.pipeline()
        .addLast(new DelimiterBasedFrameDecoder(2048,Unpooled.copiedBuffer("$$__".getBytes())))//$__为包的分隔符2048是限制一个包的最大字节数。如果超过将会报异常
        .addLast("decoder",new StringDecoder())//接收到数据 自动将将buffer转换为String 避免自己再转
        .addLast("encoder",new StringEncoder())//发送数据 可以直接发送String 框架内部转换为buffer传输
        .addLast(new ServerHandle(server));
    }

}
复制代码

客户端

复制代码
package com.liqiang.nettyTest2;

public class nettyMain {
    public static void main(String[] args) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                Server server = new Server(8081);
                server.start();

            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                Client client1=new Client("127.0.0.1", 8081);
                client1.connection();
                client1.sendMsg("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. His book w"  
                        + "ill give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the process "  
                        + "of configuring and connecting all of Netty’s components to bring your learned about threading models in ge"  
                        + "neral and Netty’s threading model in $$__particular, whose performance and consistency advantages we discuss"  
                        + "ed in detail In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. Hi"  
                        + "s book will give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the"  
                        + " process of configuring and connecting all $$__of Netty’s components to bring your learned about threading "  
                        + "models in general and Netty’s threading model in particular, whose performance and consistency advantag"  
                        + "es we discussed in detailIn this chapter you general, we recommend Java Concurrency in Practice by Bri"  
                        + "an Goetz. His book will give We’ve reached an exciting point—in the next chapter;the counter is: 1 2222"  
                        + "sdsa ddasd asdsadas dsadasdas$__");
            }
        }).start();
    }
}
复制代码

根据$__数据被拆分成了三个包

posted @   意犹未尽  阅读(484)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示