tcp通信,解决断包、粘包的问题
1、TCP和UDP的区别
- TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的(数据没有界限)。
- UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。
这样就会造成如下三种情况:
1.接收端依次从发送端接收Msg1,Msg2;(正常)
2.Msg1被发送端分割为多段发送给接收端(或者接收端先接收到Msg1和Msg2的部分数据,再接收到msg2剩下的数据);(断/拆包)
3.Msg1和Msg2粘和在一起被发送端一次发送给接收端;(粘包)
PS:因此,通常我们需要将接收的消息通过整理,然后分别合成一个我们需要的数据包,然后才将这个消息发送给接收端。
2、解决TCP断包、粘包的的代码
1. 协议如下
|
报头 |
长度 |
数据段(N个字节) |
校验和 |
||||
|
0x55AA |
len |
命令类型(id) |
目标地址 |
主机地址 |
预留 |
其它 |
CRC |
|
2 个字节 |
2 个字节(从报头到检验和所有长度) |
n1个字节 |
n2个字节 |
n3个字节 |
n3个字节 |
n4个字节 |
1个字节(从报头到数据完的校验和)。 |
2.代码如下:
void TcpClient::rcvSlot()
{
static QByteArray allBa; //用来存所有文件
allBa.append(tcpClient->readAll()); //读取数据
int head = allBa.indexOf(HEAD); //报文头的位置,HEAD=0x55aa
uint16_t length = 0; //报文(协议中)的长度
QByteArray currentBa;
bool checkResult = false;
while (-1 != head) //报文头检验
{
allBa = allBa.mid(head); //去掉报头之前的
memcpy(&length, allBa.data() + 2, 2);
if (allBa.size() >= length) //长度够,进行解析。报文长度校验
{
currentBa = allBa.mid(0, length); //获取当前完整包
id = Mymethod:isCRC(currentBa); //报文的和校验和id校验。(校验通过返回大于0,异常返回-1)
if ( id) //通过校验将数据发送
{
emit getPacketSignal(id, currentBa);
qDebug() << "接收指令:" << currentBa.toHex().toUpper();
allBa.remove(0,length+position); //通过校验去掉取出的内容和报文头之前的内容
}
else
allBa.remove(0,position+2); //未通过校验则去掉报文头
}
else
break;
head = allBa.indexOf(HEAD); //刷新报文头的位置
}
}
PS:本人第一次写,若有不足之处请大家多多指出,希望能够和大家一起持续进步!
tcp通信,解决断包、粘包的问题的更多相关文章
- UNIX网络编程——tcp流协议产生的粘包问题和解决方案
我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...
- Socket 编程中,TCP 流的结束标志与粘包问题
因为 TCP 本身是无边界的协议,因此它并没有结束标志,也无法分包. socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机 ...
- [转]java nio解决半包 粘包问题
java nio解决半包 粘包问题 NIO socket是非阻塞的通讯模式,与IO阻塞式的通讯不同点在于NIO的数据要通过channel放到一个缓存池ByteBuffer中,然后再从这个缓存池中读出数 ...
- tcp流协议产生的粘包问题和解决方案
我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...
- C#网络编程学习(5)---Tcp连接中出现的粘包、拆包问题
本文参考于CSDN博客wxy941011 1.疑问 我们使用第四个博客中的项目. 修改客户端为:连接成功后循环向服务器发送从1-100的数字.看看服务器会不会正常的接收100次数据. 可是我们发现服务 ...
- Python 32 通信循环 连接循环 粘包问题
一:通信循环 二:连接循环 三:粘包问题
- Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)
server端: package main import ( "bufio" "encoding/binary" "fmt" "n ...
- tcp协议传输中的粘包问题
什么是粘包问题 tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. ...
- netty10---分包粘包
客户端:根据 长度+数据 方式发送 package com.server; import java.net.Socket; import java.nio.ByteBuffer; public cla ...
- 网络编程3 网络编程之缓冲区&subprocess&粘包&粘包解决方案
1.sub简单使用 2.粘包现象(1) 3.粘包现象(2) 4.粘包现象解决方案 5.struct学习 6.粘包现象升级版解决方案 7.打印进度条
随机推荐
- Hexo next主题添加站内搜索功能
根据关键字搜索博文,站内搜索的功能很实用.hexo开启站内搜索很方便,已经有现成的插件可以使用,也是为了方便自己 安装插件 npm install hexo-generator-search --sa ...
- CSIC_716_20191205【TCP-解决粘包问题、UDP模板】
---------------------------------------------------------------------------------------------------- ...
- jq-demo-楼梯效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- js求100以内的素数
//打印2~100之间的数 ; i< ; i++){ var a = true; ; j < i; j++){ //判断i能否被j整除 ){ //能被整除则说明不是素数,修改布尔值为fal ...
- [Grt]一篇简单概括XML
一.XML基础 XML主要用途(我认为就这三点): XML 把数据从 HTML 分离 XML 简化数据共享 XML 简化数据传输 XML 语法规则: XML 文档必须有根元素 XML 文档必须有关闭标 ...
- mysql 删除同样记录只保留一条
delete from fa_order_account ) as a) ) as b)
- 阿里云成为Hyperledger超级账本全球会员,发力区块链生态建设
摘要: 阿里云将会与Hyperledger社区共同推进全球区块链技术和商业生态在多行业领域的建设. 2018年12月12日在瑞士巴塞尔的2018Hyperledger全球峰会上,阿里云正式加入Hype ...
- 【Codeforces 1148B】Born This Way
[链接] 我是链接,点我呀:) [题意] 有人要从A地飞向B地,然后从B地飞向C地. 给出A,B地的n.m个航班的出发时间. 已知从A到B的航班都是ta和tb时长到达B.C 只有到达B的时候航班还没起 ...
- 01退背包——bzoj2287
退背包就是限制某一件物品不可取的方案数 先做出无限制的方案数,然后对于当前不可取的物品,dp2[j]表示不取改物品情况下,取得体积为j的方案数 有状态方程 dp2[j]=dp1[j]-dp2[j-w[ ...
- NX二次开发-获取矩阵值UF_CSYS_ask_matrix_values
NX9+VS2012 #include <uf.h> #include <uf_csys.h> UF_initialize(); //获取WCS标识 tag_t WcsId = ...