TCP粘包的拆包处理

因为TCP是流式处理的,所以包没有边界,必须设计一个包头,里面表示包的长度(一般用字节表示),根据这个来逐个拆包。如果对于发送/接收频率不高的话,一般也就不做拆包处理了,因为不大可能有粘包现象。

以下是粘包和拆包的分析:

http://blog.csdn.net/zhangxinrun/article/details/6721495

用Qt的TCPSocket读出的数据来拆:

http://www.aiuxian.com/article/p-1732805.html

我是根据以上链接例子Qt的逻辑来实现的,用Boost的ASIO来读取,是同步的:

 1 m_imp->m_thread = boost::make_shared<boost::thread>(
 2             [=]()
 3             {
 4                 while (!boost::this_thread::interruption_requested())
 5                 {
 6                     boost::this_thread::interruption_point();
 7
 8                     try
 9                     {
10                         boost::system::error_code ec;
11                         std::vector<uint8_t> tmpreadBuffer(1024 * 500);
12
13                         size_t bytes_transferred = m_imp->m_sockPtr->read_some(boost::asio::buffer(tmpreadBuffer), ec);
14
15                         std::cout << "Byte Transfered:" << bytes_transferred << "\n";
16
17                         if (!ec)
18                         {
19
20                             if (bytes_transferred == 0)  continue;
21
22                             if (bytes_transferred < MSG_HEAD_SIZE)
23                             {
24                                 m_imp->m_readBuffer.insert(m_imp->m_readBuffer.end(), tmpreadBuffer.begin(), tmpreadBuffer.begin() + bytes_transferred / sizeof(uint8_t));
25                                 continue;
26                             }
27                             else
28                             {
29                                 m_imp->m_readBuffer.insert(m_imp->m_readBuffer.end(), tmpreadBuffer.begin(), tmpreadBuffer.begin() + bytes_transferred / sizeof(uint8_t));
30
31                                 size_t totalSize = m_imp->m_readBuffer.size()*sizeof(uint8_t);
32
33                                 while (totalSize)
34                                 {
35                                     size_t msgSize = m_imp->getMsgLen();
36                                     std::cout << "Msg Size is:" << msgSize << "\n";
37
38                                     std::vector<uint8_t>::const_iterator first = m_imp->m_readBuffer.begin();
39                                     std::vector<uint8_t>::const_iterator last = m_imp->m_readBuffer.begin() + msgSize / sizeof(uint8_t);
40                                     std::vector<uint8_t> tmpMsg(first, last);
41
42                                     m_imp->m_msgQueue.push_back(tmpMsg);
43
44                                     m_imp->m_readBuffer.erase(first, last);
45
46                                     totalSize = m_imp->m_readBuffer.size()*sizeof(uint8_t);
47
48
49                                 }
50
51                             }
52
53
54
55
56
57
58                         }
59                         else
60                         {
61                             std::cerr << "recv error : RAC module!" << ec.message() << std::endl;
62                             m_imp->m_sockPtr->close();
63                             break;
64                         }
65                     }
66                     catch (std::exception& e)
67                     {
68                         std::cerr << e.what() << std::endl;
69                         m_imp->m_sockPtr->close();
70                         break;
71                     }
72                 }
73             }
74
75
76
77             );

以下一个附带干货,以前一直不太理解Qt的TCPSocket,下面是底层原理:

http://blog.csdn.net/ying_593254979/article/details/17006507

时间: 2024-10-12 16:34:14

TCP粘包的拆包处理的相关文章

TCP粘包,拆包及解决方法

粘包拆包问题是处于网络比较底层的问题,在数据链路层.网络层以及传输层都有可能发生.我们日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中. 什么是粘包.拆包? 假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据可以分为三种,现列举如下: 第一种情况,接收端正常收到两个数据包,即没有发生拆包和粘包的现象,此种情况不在本文的讨论范围内. 第二种情况,接收端只收到一个数据包,由于TC

关于TCP粘包和拆包的终极解答

关于TCP粘包和拆包的终极解答 程序员行业有一些奇怪的错误的观点(误解),这些误解非常之流行,而且持有这些错误观点的人经常言之凿凿,打死也不相信自己有错,实在让人啼笑皆非.究其原因,还是因为这些错误观点所对应的正确观点不符合人的正常思维习惯,是扭曲人的直观感受的. 有两个错误观点非常之经典,一而再,再而三的出现,就跟韭菜一样,割不完,还越长越多.一是经典的"服务器最多65536个连接"误解,打开链接看介绍.另一个就是这里要讲的TCP"粘包"和"拆包&quo

netty 解决TCP粘包与拆包问题(二)

TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法. 1.消息固定长度 2.第一篇讲的回车换行符形式 3.以特殊字符作为消息结束符的形式 4.通过消息头中定义长度字段来标识消息的总长度 一.采用指定分割符解决粘包与拆包问题 服务端 1 package com.ming.netty.nio.stickpack; 2 3 4 5 import java.net.InetSocketAddress; 6 7 import io.netty.bootstrap.ServerB

TCP粘包和拆包

TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包.这样,接收端,就难于分辨出来了,必须提供科学的拆包机制.即面向流的通信是无消息保护边界的.        图解TCP的粘包和拆包 假设客户端分别发送了两个数据包D1和

封装一个带大小的封包,防止Tcp粘包、拆包

C++ 头文件 #ifndef TCPWRAP_H #define TCPWRAP_H #include <memory> #include <netinet/in.h> #include <string.h> #pragma pack(push,1) typedef struct { size_t length; //包头(包体长度) char* body; //包体 }Packet; #pragma pack(pop) class TcpDataWrap { pri

netty 解决TCP粘包与拆包问题(三)

今天使用netty的固定长度进行解码 固定长度解码的原理就是按照指定消息的长度对消息自动解码. 在netty实现中,只需要采用FiexedLengthFrameDecoder解码器即可... 以下是服务端代码 1 package com.ming.netty.nio.stickpack; 2 3 4 5 import java.net.InetSocketAddress; 6 7 import io.netty.bootstrap.ServerBootstrap; 8 import io.net

关于TCP的粘包和拆包

问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况,Data1和Data2都分开发送到了Server端,没有产生粘包和拆包的情况. 2. 第二种情况,Data1和Data2数据粘在了一起,打成了一个大的包发送到Server端,这个情况就是粘包. 3. 第三种情况,Data2被分离成Data2_1和Data2_2,并且Data2_1在Data1之前到

TCP粘包/拆包问题

无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包/拆包 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. TCP粘包/拆包问题说明 假设客户

Netty(三)TCP粘包拆包处理

tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D2给服务端,由于服务端一次性读取到的字节数是不确定的,所以可能存在以下4种情况. 1.服务端分2次读取到了两个独立的包,分别是D1,D2,没有粘包和拆包: 2.服务端一次性接收了两个包,D1和D2粘在一起了,被成为TCP粘包; 3.服务端分2次读取到了两个数据包,第一次读取到了完整的D1和D2包的部