示例:Netty 处理 TCP数据分包协议
2015-08-24 15:42
627 查看
一个、Netty解决TCP协议的数据分包的想法
我们知道通过TCP协议发送接收数据时,假设数据过大。接收到的数据会是分包的。比方:
+-----+-----+-----+
发送数据是: | ABC | DEF | GHI |
+-----+-----+-----+
而我们想接受到的数据是: | ABCDEFGHI |
该怎样处理这样的情况呢?Netty提供了一个专门处理TCP协议数据的Handler:LengthFieldBasedFrameDecoder ,它的原理是server端和client约定一个协议格式:数据包=协议长度+协议体
--------------------------------数据包------------------------------
| 协议长度部分(接收数据长度) | 协议体部分(要接收的数据)|
[align=left]举个样例,假如我们的TCPclient发送了10MB字节的数据,怎样让Nettyserver一次就接收到这10MB数据呢?那就须要client告诉服务端我发送的数据大小是多少,即在发送的数据中增加一个“数据包长度”就可以,上面提到的Handler就是用来和client约定这个协议格式的,它有几个參数,以下我介绍一下它的參数意义:[/align]
[align=left] int maxFrameLength:定义接收数据包的最大长度,假设发送的数据包超过此值。则抛出异常;[/align]
[align=left] int lengthFieldOffset:长度属性部分的偏移值,0表示长度属性位于数据包头部。[/align]
int lengthFieldLength:长度属性的字节长度,假设设置为4,就是我们用4个字节存放数据包的长度;
int lengthAdjustment:协议体长度调节值,修正信息长度,假设设置为4,那么解码时再向后推4个字节。
int initialBytesToStrip:跳过字节数,如我们想跳过长度属性部分。
二、实例-client发送10MB字节的数据。Netty服务端一次接收到所有10MB数据
client:定义一个消息体,用头部四个字节存放数据包长度
Netty服务端:定义一个LengthFieldBasedFrameDecoder(1024*1024*1024, 0, 4,0,4))。最大数据量是1GB,长度属性位于数据包头部,占4个字节,协议体调节值为0,跳过头部协议长度四个字节
三、总结:client和服务端定义消息格式必须一致
我们知道通过TCP协议发送接收数据时,假设数据过大。接收到的数据会是分包的。比方:
+-----+-----+-----+
发送数据是: | ABC | DEF | GHI |
+-----+-----+-----+
而我们想接受到的数据是: | ABCDEFGHI |
该怎样处理这样的情况呢?Netty提供了一个专门处理TCP协议数据的Handler:LengthFieldBasedFrameDecoder ,它的原理是server端和client约定一个协议格式:数据包=协议长度+协议体
--------------------------------数据包------------------------------
| 协议长度部分(接收数据长度) | 协议体部分(要接收的数据)|
[align=left]举个样例,假如我们的TCPclient发送了10MB字节的数据,怎样让Nettyserver一次就接收到这10MB数据呢?那就须要client告诉服务端我发送的数据大小是多少,即在发送的数据中增加一个“数据包长度”就可以,上面提到的Handler就是用来和client约定这个协议格式的,它有几个參数,以下我介绍一下它的參数意义:[/align]
[align=left] int maxFrameLength:定义接收数据包的最大长度,假设发送的数据包超过此值。则抛出异常;[/align]
[align=left] int lengthFieldOffset:长度属性部分的偏移值,0表示长度属性位于数据包头部。[/align]
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和服务端定义消息格式必须一致
相关文章推荐
- POJ 1087 网络流(最大流 ISAP)
- Android-非常棒的HTTP通讯总结
- Android OkHttp完全解析 是时候来了解OkHttp了
- Android OkHttp完全解析 是时候来了解OkHttp了
- at org.apache.coyote.http11.AbstractOutputBuffer.checkLengthBeforeWrite
- Linux网络编程--TCP网络编程基础(简单的server/client模型)
- 使用 cURL 进行 HTTP 请求实例
- 使用net模块实现基于TCP的数据通信
- Chapter 4 分布式(网络)存储系统
- Android 网络--我是怎么做的: Volley+OkHttp+Https
- java代码实现如jsp页面的form请求方式二HttpClient
- 又见GCD(http://acm.hdu.edu.cn/showproblem.php?pid=2504)
- Neural Networks for Machine Learning by Geoffrey Hinton (4)
- 调试打印ethhdr,iphdr,tcphdr和指定长度的内存块
- 计算机应用——DOS命令下的网络管理和诊断-终
- 计算机应用——DOS命令下的网络管理和诊断-续
- HTTP状态码(HTTP Status Code)
- Util:跟网络相关的工具类
- 黑马程序员----Java网络编程
- golang net/http包使用