博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.Netty的粘包、拆包(一)
阅读量:6204 次
发布时间:2019-06-21

本文共 7804 字,大约阅读时间需要 26 分钟。

Netty粘包、拆包

1.什么是拆包、粘包

(1)拆包、粘包介绍

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

(2)图解

1422573-20181012191854912-1313717462.png

(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
    () { @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. 添加依赖

    4.0.0
    com.xm
    netty
    0.0.1-SNAPSHOT
    io.netty
    netty-all
    5.0.0.Alpha2
  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<<<

转载于:https://www.cnblogs.com/TimerHotel/p/netty02.html

你可能感兴趣的文章
比特币,以太坊......区块链技术真的被认同了吗?
查看>>
WebLogic调用WebService提示Failed to localize、Failed to create WsdlDefinitionFeature
查看>>
020-Spring Boot 监控和度量
查看>>
JAVA中动态编译的简单使用
查看>>
java基础-BigDecimal类常用方法介绍
查看>>
[转]kafka介绍
查看>>
Google Guava新手教程
查看>>
tensorflow 实现逻辑回归——原以为TensorFlow不擅长做线性回归或者逻辑回归,原来是这么简单哇!...
查看>>
Spark 键值对RDD操作
查看>>
004-docker常用命令[二]-容器操作ps,top,attach,export
查看>>
Nancy简单实战之NancyMusicStore(四):实现购物车
查看>>
WIN10系统 截图或者某些程序时屏幕会自动放大怎么办
查看>>
[SQL] 请教一下 count里面有case when 一般情况下啥时候用
查看>>
山羊与汽车游戏的实验算法
查看>>
docker保存日志文件到本地
查看>>
【转载】springboot:如何优雅的使用mybatis
查看>>
java实现无序数组结构
查看>>
32位JDK和64位JDK
查看>>
IntelliJ IDEA 运行 Maven 项目
查看>>
Java常用的八种排序算法与代码实现
查看>>