QTcpSocket 通讯 (处理粘包)( 服务器、客户端、封包、解包 )

QTcpSocket 通讯 ( 服务器、客户端、封包、解包 )

2017年10月08日 15:48:11 lthcth111 阅读数 1403更多

分类专栏: Qt

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/lthcth111/article/details/78175341

 

转载请注明出处:http://blog.csdn.net/lthcth111/article/details/78175341

一、简介

简单实现 QTcpSocket  通讯,包含有服务器、客户端界面,和封包、解包过程,示例界面如下。

 

二、数据包结构

注:长度 = sizeof( 包类型 + 数据 + 包尾 )

 

三、部分代码展示

  • 封包
 
  1. // 封包并发送

  2. void SocketClient::send(QByteArray data, QByteArray dataType)

  3. {

  4. QTcpSocket *socket = m_dataSocket;

  5.  
  6. if(socket == NULL || (socket != NULL &&

  7. socket->state() != QTcpSocket::ConnectedState))

  8. {

  9. return;

  10. }

  11.  
  12. QByteArray packet = dataType + data + NET_PACKET_END; //[包类型 + 数据 + 包尾]

  13.  
  14. //长度占8字节,前面补零,如"00065536"

  15. int size = packet.size();

  16. QByteArray length = QByteArray().setNum(size);

  17. length = QByteArray(NET_PACKET_LTNGTH_BYTES, '0') + length;

  18. length = length.right(NET_PACKET_LTNGTH_BYTES);

  19.  
  20. packet.insert(0, NET_PACKET_START + length);//插入 [包头 + 数据长度]

  21.  
  22. socket->write(packet);

  23. }

 
  • 解包
 
  1. // 读取 socket 数据

  2. void SocketClient::OnReadyRead()

  3. {

  4. QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());

  5.  
  6. if(socket == m_dataSocket )

  7. {

  8. m_dataPacket.data += socket->readAll();

  9.  
  10. // 循环解析包数据,m_dataPacket.data 中可能不只一包数据

  11. bool isOk = false;

  12. do{

  13. isOk = parsePacket(socket, &m_dataPacket);

  14. }while(isOk);

  15. }

  16. else

  17. {

  18. MY_LOG("socket connection abnormal");

  19. }

  20. }

  21.  
  22. // 解包

  23. bool SocketClient::parsePacket(QTcpSocket *socket, SocketPacket *packet)

  24. {

  25. int pIndexStart = packet->data.indexOf(NET_PACKET_START);

  26. if(pIndexStart < 0)

  27. {

  28. return false;

  29. }

  30.  
  31. packet->data = packet->data.mid(pIndexStart); //截取从包头index_start到末尾的数据

  32. SocketPacket tmpPacket;

  33. tmpPacket.data = packet->data;

  34.  
  35. tmpPacket.data.remove(0, QByteArray(NET_PACKET_START).size());//删除包头

  36.  
  37. //解析包长度

  38. if(tmpPacket.data.count() < NET_PACKET_LTNGTH_BYTES)

  39. {

  40. return false;

  41. }

  42. bool isOk;

  43. tmpPacket.length = tmpPacket.data.mid(0, NET_PACKET_LTNGTH_BYTES).toLong(&isOk);

  44. if(isOk == false)

  45. {

  46. packet->data.remove(0, QByteArray(NET_PACKET_START).size());//删除包头

  47. if(packet->data.indexOf(NET_PACKET_START) >= 0)

  48. {

  49. return true;//有可能出现粘包的情况,继续解析后面数据

  50. }

  51. else

  52. {

  53. return false;

  54. }

  55. }

  56.  
  57. //数据到达包长度

  58. tmpPacket.data.remove(0, NET_PACKET_LTNGTH_BYTES);//删除数据长度

  59. if(tmpPacket.length > tmpPacket.data.count())

  60. {

  61. return false;

  62. }

  63.  
  64. //包尾是否匹配

  65. tmpPacket.data.resize(tmpPacket.length);//删除多余数据

  66. if(tmpPacket.data.endsWith(NET_PACKET_END) == false)

  67. {

  68. packet->data.remove(0, QByteArray(NET_PACKET_START).size());//删除包头

  69. if(packet->data.indexOf(NET_PACKET_START) >= 0)

  70. {

  71. return true;//有可能出现粘包的情况,继续解析后面数据

  72. }

  73. else

  74. {

  75. return false;

  76. }

  77. }

  78.  
  79. tmpPacket.data.resize(tmpPacket.length -

  80. QByteArray(NET_PACKET_END).count()); //删除包尾

  81.  
  82. //解析出数据类型

  83. if(tmpPacket.data.count() < NET_PACKET_TYPE_BYTES)

  84. {

  85. return false;

  86. }

  87. QByteArray dataType = tmpPacket.data.left(NET_PACKET_TYPE_BYTES);

  88. tmpPacket.dataType = dataType;

  89.  
  90. tmpPacket.data.remove(0, NET_PACKET_TYPE_BYTES);//删除数据类型

  91.  
  92.  
  93. //发送数据包消息

  94. if(socket == m_dataSocket)

  95. {

  96. emit dataPacketReady(tmpPacket);

  97. }

  98.  
  99. //删除当前包数据

  100. packet->data.remove(0,

  101. QByteArray(NET_PACKET_START).size()

  102. + NET_PACKET_LTNGTH_BYTES

  103. + tmpPacket.length);

  104.  
  105. return true;

  106. }

四、完整代码下载

CSDN 下载
客户端和服务器: http://download.csdn.net/download/lthcth111/10011256

码云下载

客户端:https://gitee.com/2649549484/TcpClientSimple

服务器: https://gitee.com/2649549484/TcpServerSimple

 

五、开发环境

Win7 + Qt 5.5.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值