TCP编程底层都有粘包和拆包机制,因为我们在C/S这种传输模型下,以TCP协议传输的时候,在网络中的byte其实就像是河水,TCP就像一个搬运工,将这流水从一端转送到另一端,这时又分两种情况:

1)如果客户端的每次制造的水比较多,也就是我们常说的客户端给的包比较大,TCP这个搬运工就会分多次去搬运。

2)如果客户端每次制造的水比较少的话,TCP可能会等客户端多次生产之后,把所有的水一起再运输到另一端

上述第一种情况,就是需要我们进行粘包,在另一端接收的时候,需要把多次获取的结果粘在一起,变成我们可以理解的信息,第二种情况,我们在另一端接收的时候,就必须进行拆包处理,因为每次接收的信息,可能是另一个远程端多次发送的包,被TCP粘在一起的

我们进行上述两种情况给出具体的场景:

1)单次发送的包内容过多的情况,拆包的现象:

我们先写客户端的bootstrap:

  1. package com.lyncc.netty.stickpackage.myself;
  2. import io.netty.bootstrap.Bootstrap;
  3. import io.netty.channel.ChannelFuture;
  4. import io.netty.channel.ChannelInitializer;
  5. import io.netty.channel.ChannelOption;
  6. import io.netty.channel.ChannelPipeline;
  7. import io.netty.channel.EventLoopGroup;
  8. import io.netty.channel.nio.NioEventLoopGroup;
  9. import io.netty.channel.socket.SocketChannel;
  10. import io.netty.channel.socket.nio.NioSocketChannel;
  11. import io.netty.handler.codec.LineBasedFrameDecoder;
  12. import io.netty.handler.codec.string.StringDecoder;
  13. public class BaseClient {
  14. static final String HOST = System.getProperty("host", "127.0.0.1");
  15. static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
  16. static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
  17. public static void main(String[] args) throws Exception {
  18. EventLoopGroup group = new NioEventLoopGroup();
  19. try {
  20. Bootstrap b = new Bootstrap();
  21. b.group(group)
  22. .channel(NioSocketChannel.class)
  23. .option(ChannelOption.TCP_NODELAY,true)
  24. .handler(new ChannelInitializer<SocketChannel>() {
  25. @Override
  26. public void initChannel(SocketChannel ch) throws Exception {
  27. ChannelPipeline p = ch.pipeline();
  28. //                     p.addLast(new LineBasedFrameDecoder(1024));
  29. p.addLast(new StringDecoder());
  30. p.addLast(new BaseClientHandler());
  31. }
  32. });
  33. ChannelFuture future = b.connect(HOST, PORT).sync();
  34. future.channel().writeAndFlush("Hello Netty Server ,I am a common client");
  35. future.channel().closeFuture().sync();
  36. } finally {
  37. group.shutdownGracefully();
  38. }
  39. }
  40. }

客户端的handler:

  1. package com.lyncc.netty.stickpackage.myself;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.buffer.Unpooled;
  4. import io.netty.channel.ChannelHandlerContext;
  5. import io.netty.channel.ChannelInboundHandlerAdapter;
  6. public class BaseClientHandler extends ChannelInboundHandlerAdapter{
  7. private byte[] req;
  8. private int counter;
  9. public BaseClientHandler() {
  10. //        req = ("BazingaLyncc is learner" + System.getProperty("line.separator"))
  11. //            .getBytes();
  12. req = ("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. His book w"
  13. + "ill give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the process "
  14. + "of configuring and connecting all of Netty’s components to bring your learned about threading models in ge"
  15. + "neral and Netty’s threading model in particular, whose performance and consistency advantages we discuss"
  16. + "ed in detail In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. Hi"
  17. + "s book will give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the"
  18. + " process of configuring and connecting all of Netty’s components to bring your learned about threading "
  19. + "models in general and Netty’s threading model in particular, whose performance and consistency advantag"
  20. + "es we discussed in detailIn this chapter you general, we recommend Java Concurrency in Practice by Bri"
  21. + "an Goetz. His book will give We’ve reached an exciting point—in the next chapter;the counter is: 1 2222"
  22. + "sdsa ddasd asdsadas dsadasdas").getBytes();
  23. }
  24. @Override
  25. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  26. ByteBuf message = null;
  27. //        for (int i = 0; i < 100; i++) {
  28. //            message = Unpooled.buffer(req.length);
  29. //            message.writeBytes(req);
  30. //            ctx.writeAndFlush(message);
  31. //        }
  32. message = Unpooled.buffer(req.length);
  33. message.writeBytes(req);
  34. ctx.writeAndFlush(message);
  35. message = Unpooled.buffer(req.length);
  36. message.writeBytes(req);
  37. ctx.writeAndFlush(message);
  38. }
  39. @Override
  40. public void channelRead(ChannelHandlerContext ctx, Object msg)
  41. throws Exception {
  42. String buf = (String) msg;
  43. System.out.println("Now is : " + buf + " ; the counter is : "+ ++counter);
  44. }
  45. @Override
  46. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  47. ctx.close();
  48. }
  49. }

服务端的serverBootstrap:

  1. package com.lyncc.netty.stickpackage.myself;
  2. import io.netty.bootstrap.ServerBootstrap;
  3. import io.netty.channel.ChannelFuture;
  4. import io.netty.channel.ChannelInitializer;
  5. import io.netty.channel.ChannelOption;
  6. import io.netty.channel.EventLoopGroup;
  7. import io.netty.channel.nio.NioEventLoopGroup;
  8. import io.netty.channel.socket.SocketChannel;
  9. import io.netty.channel.socket.nio.NioServerSocketChannel;
  10. import io.netty.handler.codec.string.StringDecoder;
  11. import java.net.InetSocketAddress;
  12. public class BaseServer {
  13. private int port;
  14. public BaseServer(int port) {
  15. this.port = port;
  16. }
  17. public void start(){
  18. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  19. EventLoopGroup workerGroup = new NioEventLoopGroup();
  20. try {
  21. ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
  22. .childHandler(new ChannelInitializer<SocketChannel>() {
  23. protected void initChannel(SocketChannel ch) throws Exception {
  24. //                            ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
  25. ch.pipeline().addLast(new StringDecoder());
  26. ch.pipeline().addLast(new BaseServerHandler());
  27. };
  28. }).option(ChannelOption.SO_BACKLOG, 128)
  29. .childOption(ChannelOption.SO_KEEPALIVE, true);
  30. // 绑定端口,开始接收进来的连接
  31. ChannelFuture future = sbs.bind(port).sync();
  32. System.out.println("Server start listen at " + port );
  33. future.channel().closeFuture().sync();
  34. } catch (Exception e) {
  35. bossGroup.shutdownGracefully();
  36. workerGroup.shutdownGracefully();
  37. }
  38. }
  39. public static void main(String[] args) throws Exception {
  40. int port;
  41. if (args.length > 0) {
  42. port = Integer.parseInt(args[0]);
  43. } else {
  44. port = 8080;
  45. }
  46. new BaseServer(port).start();
  47. }
  48. }

服务端的handler:

  1. package com.lyncc.netty.stickpackage.myself;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.channel.ChannelInboundHandlerAdapter;
  4. public class BaseServerHandler extends ChannelInboundHandlerAdapter{
  5. private int counter;
  6. @Override
  7. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  8. String body = (String)msg;
  9. System.out.println("server receive order : " + body + ";the counter is: " + ++counter);
  10. }
  11. @Override
  12. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  13. cause.printStackTrace();
  14. ctx.close();
  15. }
  16. }

照例,我们先运行服务器端:

我们再运行客户端,客户端启动后,我们再看看服务器端的控制台打印输出:

我们可以看到服务器端分三次接收到了客户端两次发送的那段很长的信息

2)单次发送的包内容过多的情况,粘包的现象:

客户端和服务端的bootstrap不改变,我们修改一下,客户端发送信息的channelActive的代码:

  1. package com.lyncc.netty.stickpackage.myself;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.buffer.Unpooled;
  4. import io.netty.channel.ChannelHandlerContext;
  5. import io.netty.channel.ChannelInboundHandlerAdapter;
  6. public class BaseClientHandler extends ChannelInboundHandlerAdapter{
  7. private byte[] req;
  8. private int counter;
  9. public BaseClientHandler() {
  10. req = ("BazingaLyncc is learner").getBytes();
  11. //        req = ("In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. His book w"
  12. //                + "ill give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the process "
  13. //                + "of configuring and connecting all of Netty’s components to bring your learned about threading models in ge"
  14. //                + "neral and Netty’s threading model in particular, whose performance and consistency advantages we discuss"
  15. //                + "ed in detail In this chapter you general, we recommend Java Concurrency in Practice by Brian Goetz. Hi"
  16. //                + "s book will give We’ve reached an exciting point—in the next chapter we’ll discuss bootstrapping, the"
  17. //                + " process of configuring and connecting all of Netty’s components to bring your learned about threading "
  18. //                + "models in general and Netty’s threading model in particular, whose performance and consistency advantag"
  19. //                + "es we discussed in detailIn this chapter you general, we recommend Java Concurrency in Practice by Bri"
  20. //                + "an Goetz. His book will give We’ve reached an exciting point—in the next chapter;the counter is: 1 2222"
  21. //                + "sdsa ddasd asdsadas dsadasdas").getBytes();
  22. }
  23. @Override
  24. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  25. ByteBuf message = null;
  26. for (int i = 0; i < 100; i++) {
  27. message = Unpooled.buffer(req.length);
  28. message.writeBytes(req);
  29. ctx.writeAndFlush(message);
  30. }
  31. //        message = Unpooled.buffer(req.length);
  32. //        message.writeBytes(req);
  33. //        ctx.writeAndFlush(message);
  34. //        message = Unpooled.buffer(req.length);
  35. //        message.writeBytes(req);
  36. //        ctx.writeAndFlush(message);
  37. }
  38. @Override
  39. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  40. ctx.close();
  41. }
  42. }

我们再次启动服务器端:

启动客户端后,依旧看服务器端的控制台:

可以看出,客户端发送100次的信息,被服务器端分三次就接收了,这就发生了粘包的现象

以上就是典型的粘包和拆包的场景

TCP粘包拆包场景的更多相关文章

  1. Netty(二)——TCP粘包/拆包

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7814644.html 前面讲到:Netty(一)--Netty入门程序 主要内容: TCP粘包/拆包的基础知 ...

  2. TCP粘包/拆包 ByteBuf和channel 如果没有Netty? 传统的多线程服务器,这个也是Apache处理请求的模式

    通俗地讲,Netty 能做什么? - 知乎 https://www.zhihu.com/question/24322387 谢邀.netty是一套在java NIO的基础上封装的便于用户开发网络应用程 ...

  3. TCP 粘包拆包

    一.什么是粘包拆包? 粘包拆包是TCP协议传输中一种现象概念.TCP是传输层协议,他传输的是“流”式数据,TCP并不知道传输是哪种业务数据,或者说,并不关心.它只是根据缓冲区状况将数据进行包划分,然后 ...

  4. Netty(三)TCP粘包拆包处理

    tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D ...

  5. TCP粘包/拆包问题

    无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包/拆包 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河 ...

  6. TCP 粘包/拆包问题

    简介    TCP 是一个’流’协议,所谓流,就是没有界限的一串数据. 大家可以想想河里的流水,是连成一片的.期间并没有分界线, TCP 底层并不了解上层业务数据的具体含义 ,它会根据 TCP 缓冲区 ...

  7. TCP粘包/拆包问题的解决

    TCP粘包拆包问题 一个完整的包可能被TCP拆分成多个包,或多个小包封装成一个大的数据包发送. 解决策略 消息定长,如果不够,空位补空格 在包尾增加回车换行符进行分割,例如FTP协议 将消息分为消息头 ...

  8. 第四章 TCP粘包/拆包问题的解决之道---4.1---

    4.1 TCP粘包/拆包 TCP是一个“流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可 ...

  9. Java网络编程基础之TCP粘包拆包

    TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想象河里的流水,他们是连成一片的,其间并没有分界线.TCP底层并不了解上层业务数据的具体含义,他会根据TCP缓冲区的实 ...

随机推荐

  1. [CSAPP笔记]Binary , Unsigned , Signed 之间的相互装换

    LaTex+MarkDown+Pandoc组合套件写博客的处女作,试试效果.各自的分工为:Latex下编辑公式,在Sublime Text 2下使用Markdown排版,最后用Pandoc导出. 摘要 ...

  2. python之List排序

    sorted() #coding:utf-8 #sorted Ascending 升序 L = [12,23,43,3,65,34,21,3645] print(sorted(L)) >> ...

  3. Python中的collections模块

    Python中内置了4种数据类型,包括:list,tuple,set,dict,这些数据类型都有其各自的特点,但是这些特点(比如dict无序)在一定程度上对数据类型的使用产生了约束,在某些使用场景下效 ...

  4. [转](阿里笔试)使用多线程和sleep函数生成字符串的伪随机排列

    http://blog.csdn.net/jiaowopan/article/details/12009079 C/C++(Linux平台) 注意编译连接时需要链接pthread库,即g++ XX.c ...

  5. VBA遍历单元格

    Sub test() Dim str Dim i, j i = j = ).UsedRange.Rows.Count ).UsedRange.Columns.Count ).Cells(r, c).V ...

  6. ofdm理解(转载)

    说明:以下文字,灰色为吹水文,黑色为正文,蓝色为采用实际应用中的参数所作的说明. 起因是这样的.时间回到07年底,4G方兴之时,同桌隔壁的隔壁"小白"同学说看不太明白OFDMA的原 ...

  7. Maven中配置生成单元测试报告配置

    对junit单元测试的报告: 1.  ------------------------------------------------------- 2.   T E S T S 3.  ------ ...

  8. phpMyAdmin“缺少 mcrypt 扩展。请检查 PHP 配置。”解决办法

    在ecmall二次开发中因php版本要求低于5.3,而如下更新要求升级PHP,所以以下方式不适合于ecmall商城项目. 解决办法:安装php-mcrypt libmcrypt libmcrypt-d ...

  9. 使用Maven运行Solr(翻译)

    Solr是一个使用开源的搜索服务器,它采用Lucene Core的索引和搜索功能构建,它可以用于几乎所有的编程语言实现可扩展的搜索引擎. Solr的虽然有很多优点,建立开发环境是不是其中之一.此博客条 ...

  10. Linux 制作补丁 打补丁 撤销补丁

    1.制作补丁 diff - 逐行比较文件 格式 diff   参数   旧文件/旧文件夹   新文件/新文件夹 -N   将不存在的文件看作是空的 -a   将所有文件都视为文本文件 -u   以合并 ...