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             );
View Code

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
st_asio_wrapper是一组类库,功能是对boost.asio的装(调试环境:boost-1.51.0),目的是简化boost.asio开发; 其特点是效率高、跨平台、完全异步(当然这是从boost.asio继承而来)、自动重连,数据透明传输,自动解决分问题(你可以像udp一样使用它); 注:只支持tcp协议; 教程:http://blog.csdn.net/yang79tao/article/details/7724514 2.3版更新内容: 消息(std::string装)不再用boost::shared_ptr装,之前有过度使用智能指针之嫌。效率上,std::string如果支持引用记数,或者编译器支持std::move语义,是没有损失的(因为也不存在内存的拷贝,反而省了智能指针使用上的开销),幸好vc支持std::move语义(虽然它不支持引用记数,linux则都支持)。这样带来一个问题,原来所有的接口中的boost::shared_ptr<std::string>数据类型,全部换成了std::string引用,升级到2.3的朋友要注意修改之前重写虚函数的签名,如果不改,则重写肯定不生效,变成了新增加虚函数了(因为签名不一样)。这样向大家道歉,接口签名以后应该不会变化了,但可能增加接口; 修复使用std::advance的一个BUG,此BUG在linux下不存在,这里顺便向大家说一下,std::advance在vc和gcc下面,语义一样,但处理方式有些不同,一定要注意; 增加了个专门用于服务端压力测试的客户端框架st_test_client,并写了一个demo test_client,可以在performance_test目录下面找到; 把连接服务端逻辑从st_client剥离出来,定义了一个新的类st_connector,st_client和st_test_client将从它继承; 增加对vc2010的支持,和编译时对编译器版本的检测,如果达不到vc2010及其以上的版本,st_asio_wrapper将直接报错。
st_asio_wrapper是一组类,功能是对boost.asio的装(调试环境:boost-1.50.0),目的是简化boost.asio开发; 其特点是效率高、跨平台、完全异步,当然这是从boost.asio继承而来; 自动重连,数据透明传输,自动解决分问题(你可以像udp一样使用它); 注:只支持tcp协议; 教程:http://blog.csdn.net/yang79tao/article/details/7724514 1.1版更新内容: 增加了自定义数据模式的支持,可用于st_asio_wrapper server与其它客户端的通信、或者st_asio_wrapper client与其它服务端的通信;当然,两端都是st_asio_wrapper的话,就用透明传输即可(1.0版已经支持了)。 1.2版更新内容: 修复BUG:当stop_service之后,再start_service时,client_base内部某些成员变量可能没有得到复位; 服务端增加修改监听地址功能,当然仍然要在start_service之前调用set_server_addr函数。 1.3版更新内容: 增加自定义消息格式的发送,这个本来是在1.1版本实现的,结果我漏掉了,只实现了自定义消息格式的接收。 1.4版更新内容: 将打与解器从client_base分离出来,以简化这个日益复杂的基类; 可以在运行时修改打器。 1.5版更新内容: 增加ipv6支持,默认是ipv4,服务端和客户端都通过设置一个ipv6的地址来开启这个功能; 增加了一些服务端helper函数,小改了一下客户端set_server_addr函数签名(调换了两个参数的位置以保持和服务端一样)。 1.6版更新内容: 增加了接收消息缓存(改动较大,on_msg的语义有所变化,请看开发教程第三篇)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值