Netty粘包、拆包

1.什么是拆包、粘包

(1)拆包、粘包介绍

TCP是个“流”协议,所谓流,就是没有界限的一串数据。大家可以想想河里的流水,是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

(2)图解

(3)代码模拟

  1. 服务端Server

    package com.xm.netty.demo02;
    
    import java.net.InetSocketAddress;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.Channel;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { private final int port; public Server(int port) {
    this.port = port;
    } public static void main(String[] args) { int port = 8989;
    try {
    new Server(port).start();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } } private void start() throws InterruptedException {
    EventLoopGroup g1 = new NioEventLoopGroup();
    EventLoopGroup g2 = new NioEventLoopGroup();
    try {
    ServerBootstrap bootstrap = new ServerBootstrap();
    bootstrap
    .group(g1,g2)
    .channel(NioServerSocketChannel.class)
    .localAddress(new InetSocketAddress( port))
    .childHandler(new ChannelInitializer() {
    @Override
    protected void initChannel(Channel ch) throws Exception {
    ch.pipeline().addLast(new ServerHandler());
    }
    });
    ChannelFuture future = bootstrap.bind().sync();
    future.channel().closeFuture().sync();
    } finally {
    g1.shutdownGracefully().sync();
    g2.shutdownGracefully().sync();
    }
    } }
  2. 服务端ServerHandler

    package com.xm.netty.demo02;
    
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter; import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.util.CharsetUtil; public class ServerHandler extends ChannelHandlerAdapter { @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf in = (ByteBuf) msg;
    String str = in.toString(CharsetUtil.UTF_8);
    System.out.println("Server:"+str);
    str = "服务器返回--->"+ str;
    ctx.writeAndFlush(Unpooled.copiedBuffer(str.getBytes()));
    } @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    cause.printStackTrace();
    ctx.close();
    } @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())+"一个客户端连接!");
    } }
  3. 客户端Client

    package com.xm.netty.demo02;
    
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter; import io.netty.bootstrap.Bootstrap;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel; public class Client { private final int port;
    private final String host; public Client(int port, String host) {
    this.port = port;
    this.host = host;
    } public static void main(String[] args) {
    String host = "127.0.0.1";
    int port = 8989;
    try {
    new Client(port, host).start();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    } private void start() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup();
    try {
    Bootstrap bootstrap = new Bootstrap();
    bootstrap
    .group(group)
    .channel(NioSocketChannel.class)
    .remoteAddress(host, port)
    .handler(new ChannelInitializer<SocketChannel>() { @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ch.pipeline().addLast(new ClientHandler());
    } }); ChannelFuture future = bootstrap.connect().sync(); for(int i=10;i<20;i++) {
    String str = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now()) + "---- " +i+"<<<";
    future.channel().writeAndFlush(Unpooled.copiedBuffer(str.getBytes()));
    } future.channel().closeFuture().sync();
    } finally {
    group.shutdownGracefully().sync();
    } } }
  4. 客户端ClientHandler

    package com.xm.netty.demo02;
    
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter; import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.util.CharsetUtil;
    import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter { @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { ByteBuf in = (ByteBuf) msg;
    String str = in.toString(CharsetUtil.UTF_8);
    System.out.println("Client:"+str); } finally {
    ReferenceCountUtil.release(msg);
    }
    } @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    cause.printStackTrace();
    ctx.close();
    } @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())+" 已连接上服务器!");
    } }
  5. 添加依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xm</groupId>
    <artifactId>netty</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
    <dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>5.0.0.Alpha2</version>
    </dependency>
    </dependencies>
    </project>
  6. 预期结果

    1)服务器

    2018-10-11T18:37:19.857一个客户端连接!

    Server:2018-10-11T18:37:19.855---- 10<<<

    Server:2018-10-11T18:37:20.377---- 11<<<

    Server:2018-10-11T18:37:20.877---- 12<<<

    Server:2018-10-11T18:37:21.378---- 13<<<

    Server:2018-10-11T18:37:21.879---- 14<<<

    Server:2018-10-11T18:37:22.379---- 15<<<

    Server:2018-10-11T18:37:22.879---- 16<<<

    Server:2018-10-11T18:37:23.38---- 17<<<

    Server:2018-10-11T18:37:23.881---- 18<<<

    Server:2018-10-11T18:37:24.382---- 19<<<

    (2)客户端

    2018-10-11T18:37:19.855 已连接上服务器!

    Client:服务器返回--->2018-10-11T18:37:19.855---- 10<<<

    Client:服务器返回--->2018-10-11T18:37:20.377---- 11<<<

    Client:服务器返回--->2018-10-11T18:37:20.877---- 12<<<

    Client:服务器返回--->2018-10-11T18:37:21.378---- 13<<<

    Client:服务器返回--->2018-10-11T18:37:21.879---- 14<<<

    Client:服务器返回--->2018-10-11T18:37:22.379---- 15<<<

    Client:服务器返回--->2018-10-11T18:37:22.879---- 16<<<

    Client:服务器返回--->2018-10-11T18:37:23.38---- 17<<<

    Client:服务器返回--->2018-10-11T18:37:23.881---- 18<<<

    Client:服务器返回--->2018-10-11T18:37:24.382---- 19<<<

  7. 实际结果

    (1)服务器

    2018-10-11T18:35:40.988一个客户端连接!

    Server:2018-10-11T18:35:40.986---- 10<<<2018-10-11T18:35:41.01---- 11<<<2018-10-11T18:35:41.01---- 12<<<2018-10-11T18:35:41.01---- 13<<<2018-10-11T18:35:41.01---- 14<<<2018-10-11T18:35:41.01---- 15<<<2018-10-11T18:35:41.01---- 16<<<2018-10-11T18:35:41.01---- 17<<<2018-10-11T18:35:41.01---- 18<<<2018-10-11T18:35:41.01---- 19<<<

    (2)客户端

    2018-10-11T18:35:40.986 已连接上服务器!

    Client:服务器返回--->2018-10-11T18:35:40.986---- 10<<<2018-10-11T18:35:41.01---- 11<<<2018-10-11T18:35:41.01---- 12<<<2018-10-11T18:35:41.01---- 13<<<2018-10-11T18:35:41.01---- 14<<<2018-10-11T18:35:41.01---- 15<<<2018-10-11T18:35:41.01---- 16<<<2018-10-11T18:35:41.01---- 17<<<2018-10-11T18:35:41.01---- 18<<<2018-10-11T18:35:41.01---- 19<<<

最新文章

  1. Bootstrap相关资料
  2. 支持Java Spring MVC
  3. JAVASCRIPT实现简单计算器
  4. MSsql bcp
  5. HTML元素的ID和Name属性的区别
  6. HTML初学者常用标签及属性
  7. MatlabR2015b用了一段时间之后需要重新激活
  8. BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)
  9. 利用Node的chokidar 监听文件改变的文件。
  10. Linux 系统化学习系列文章总目录(持续更新中)
  11. PeopleSoft 单点登录
  12. 为什么zookeeper集群中节点配置个数是奇数个?
  13. 2012年NOIP普及组 摆花
  14. 【Tensorflow】tensorboard
  15. CentOS 7卸载Docker
  16. Navicat 12破解工具 +安装包
  17. java基础27 单例集合Collection及其常用方法
  18. python邮件
  19. Mysql 表锁定的问题
  20. 第2天:JavaScript基础(运算符、案例、循环、冒泡以及prompt提示输入框)

热门文章

  1. maya2018无法安装卸载激活失败
  2. maya2015安装失败如何卸载重装
  3. derby
  4. 快速创建jquery插件
  5. redis开机启动,有密码
  6. 内存分配详解 malloc, new, HeapAlloc, VirtualAlloc,GlobalAlloc
  7. Android学习记录帖
  8. OSI七层模型含义
  9. Android实现异步的几种方法
  10. gradle方式集成融云sdk dlopen failed: library &quot;libsqlite.so&quot; not found