一个、Netty解决TCP协议的数据分包的想法



我们知道通过TCP协议发送接收数据时,假设数据过大。接收到的数据会是分包的。比方:

                         
          +-----+-----+-----+

         发送数据是: | ABC | DEF | GHI |

                            +-----+-----+-----+
         而我们想接受到的数据是: | ABCDEFGHI |

该怎样处理这样的情况呢?Netty提供了一个专门处理TCP协议数据的Handler:LengthFieldBasedFrameDecoder ,它的原理是server端和client约定一个协议格式:数据包=协议长度+协议体

      --------------------------------数据包------------------------------

   
 | 协议长度部分(接收数据长度) | 协议体部分(要接收的数据)|

举个样例,假如我们的TCPclient发送了10MB字节的数据,怎样让Nettyserver一次就接收到这10MB数据呢?那就须要client告诉服务端我发送的数据大小是多少,即在发送的数据中增加一个“数据包长度”就可以,上面提到的Handler就是用来和client约定这个协议格式的,它有几个參数,以下我介绍一下它的參数意义:
     int maxFrameLength:定义接收数据包的最大长度,假设发送的数据包超过此值。则抛出异常;
     int lengthFieldOffset:长度属性部分的偏移值,0表示长度属性位于数据包头部。
     int lengthFieldLength:长度属性的字节长度,假设设置为4,就是我们用4个字节存放数据包的长度;
     int lengthAdjustment:协议体长度调节值,修正信息长度,假设设置为4,那么解码时再向后推4个字节。
     int initialBytesToStrip:跳过字节数,如我们想跳过长度属性部分。

二、实例-client发送10MB字节的数据。Netty服务端一次接收到所有10MB数据

client:定义一个消息体,用头部四个字节存放数据包长度

public byte[] send(byte[] sendData) throws UnknownHostException, IOException {
Socket socket = new Socket(serverIp, serverPort);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
byte resultArray[] = null;
try {
// 定义一个发送消息协议格式:|--header:4 byte--|--content:10MB--|
// 获取一个4字节长度的协议体头
byte[] dataLength = intToByteArray(4, sendData.length);
// 和请求的数据组成一个请求数据包
byte[] requestMessage = combineByteArray(dataLength, sendData);
//发送数据-------------------------------
os.write(requestMessage);
os.flush();
//接收数据-------------------------------
resultArray = IOUtils.toByteArray(is);
} catch (Exception e) {
e.printStackTrace();
} finally {
os.close();
is.close();
socket.close();
}
return resultArray;
}
private static byte[] intToByteArray(int byteLength, int intValue) {
return ByteBuffer.allocate(byteLength).putInt(intValue).array();
}
private static byte[] combineByteArray(byte[] array1, byte[] array2) {
byte[] combined = new byte[array1.length + array2.length];
System.arraycopy(array1, 0, combined, 0, array1.length);
System.arraycopy(array2, 0, combined, array1.length, array2.length);
return combined;
}

Netty服务端:定义一个LengthFieldBasedFrameDecoder(1024*1024*1024, 0, 4,0,4))。最大数据量是1GB,长度属性位于数据包头部,占4个字节,协议体调节值为0,跳过头部协议长度四个字节

@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framedecoder",new LengthFieldBasedFrameDecoder(1024*1024*1024, 0, 4,0,4));
pipeline.addLast(new TCPServiceHandler());// 处理业务Handler }

三、总结:client和服务端定义消息格式必须一致

版权声明:本文博客原创文章。博客,未经同意,不得转载。

示例:Netty 处理 TCP数据分包协议的更多相关文章

  1. netty同端口监听tcp和websocket协议

    前言: 软件通信七层结构(osi模型)中由协议套协议最终组成最高级应用层协议(http等等),下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做 ...

  2. TCP和UDP 协议发送数据包的大小

    在进行UDP编程的时候,我们最容易想到的问题就是,一次发送多少bytes好? 当然,这个没有唯一答案,相对于不同的系统,不同的要求,其得到的答案是不一样的,这里仅对像ICQ一类的发送聊天消息的情况作分 ...

  3. TCP/IP UDP 协议首部及数据进入协议栈封装的过程

    数据的封装 UDP 封装 TCP 封装 IP 封装 检验和算法 当应用程序用TCP传送数据时,数据被传送入协议栈中,然后逐一通过每一层直到被当作一串比特流送入网络 注: UDP数据TCP数据基本一致. ...

  4. 韩顺刚-tcp报文头协议详细分析第一包数据:序号是0,发送数据的长度是0,因为没有收到对端的数据,所以确认号是0, Syn的标志位设置成1,这里没有发送的数据,只发送TCP的20个字节的头部

    TCP报文段首部格式 大部分TCP报文头部都是20个字节,有的数据包要加上选项. 上面一行代表4个字节,源端口和目的端口都是2个字节. TCP协议是面向字节流的协议 TCP是一段一段分块的发送数据的 ...

  5. Fixed-Length Frames 谈谈网络编程中应用层(基于TCP/UDP)的协议设计

    http://blog.sina.com.cn/s/blog_48d4cf2d0101859x.html 谈谈网络编程中应用层(基于TCP/UDP)的协议设计 (2013-04-27 19:11:00 ...

  6. netty(4)高级篇-Websocket协议开发

    一.HTTP协议的弊端 将HTTP协议的主要弊端总结如下: (1) 半双工协议:可以在客户端和服务端2个方向上传输,但是不能同时传输.同一时刻,只能在一个方向上传输. (2) HTTP消息冗长:相比于 ...

  7. 网络基础之 tcp/ip五层协议 socket

    1 网络通信协议(互联网协议) 1.1 互联网的本质就是一系列的网络协议 1.2 osi七层协议 1.3 tcp/ip五层模型讲解 1.3.1 物理层 1.3.2 数据链路层 1.3.3 网络层 1. ...

  8. 东哥讲义2 - 基于TCP,UDP协议的攻击,分析与防护

    TCP SYN FLOOD 攻击 正常的TCP三次握手过程: 处于SYN FLOOD攻击状态时的三次握手过程: 查看示例:x_syn.c文件,一个实现了自定义mac,ip,tcp头部的syn floo ...

  9. Netty处理TCP拆包、粘包

    Netty实践(二):TCP拆包.粘包问题-学海无涯 心境无限-51CTO博客 http://blog.51cto.com/zhangfengzhe/1890577 2017-01-09 21:56: ...

随机推荐

  1. AlarmManager的学习与实现

    综述     这个类提供了一种使用系统提供的alarm服务.这个服务同意用户安排他们的应用程序在将来的某一个时间点执行.当设置的alarm响起,那么之前系统为这个alarm注冊的Intent就会自己主 ...

  2. jQuery Fancybox插件说明

    这里有jquery影像回放路径插件称为Fancybox,项目主页地址:http://fancybox.net/ Fancybox的特点例如以下: 1.能够支持图片.html文本.flash动画.ifr ...

  3. freemarker导出word带图片

    导出word带图片 如果你需要在word中添加图片,那你就在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码: <w:binData w:nam ...

  4. 《深入浅出 Java Concurrency》—锁紧机构(一)Lock与ReentrantLock

    转会:http://www.blogjava.net/xylz/archive/2010/07/05/325274.html 前面的章节主要谈谈原子操作,至于与原子操作一些相关的问题或者说陷阱就放到最 ...

  5. JDK8在Java转让Javascript脚本引擎动态地定义和运行代码

    import java.lang.*; import java.util.Arrays; import java.util.List; import javax.script.Invocable; i ...

  6. macbook连接linuxserver后不显示matlab桌面[问题]

    macbook 登录远程linuxserver.Macbook今天,系统版本号10.9.4.这是更新,打开matlab当提醒x11不存在.一个接着安装Xquarz2.7.6. matlab它可以在本地 ...

  7. == 和 equal

    ==比较是地址 equal比较的是值 Integer r1 = new Integer(900);//定义r1整型对象 Integer r2 = new Integer(900);//定义r2整型对象 ...

  8. 【Linux驱动】TQ2440 LED驱动程序

    ★整体介绍 LED驱动程序主要实现了TQ2440开发板上的4个LED灯的硬件驱动,实现了对引脚GPIOB5.GPIOB6.GPIOB7.GPIOB8的高低电平设置(common-smdk.c中已经实现 ...

  9. Linux学习记录--命名管道通信

    命名管道通信 什么是命名管道 一个主要的限制是,它是匿名管道的应用还没有名字,因此,只有它可以用于进程间通信的方式与亲缘关系.在命名管道(named pipe或FIFO)提出后,该限制得到了克服.FI ...

  10. Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器

    转载标明出处:http://blog.csdn.net/lmj623565791/article/details/26938985 继续并发,貌似并发的文章很少有人看啊~哈~ 今天准备详细介绍java ...