TCP协议.之发送数据,粘包,拆包问题(二)

news/2024/5/17 18:00:28 标签: tcp

Tcp协议发送数据,粘包,拆包问题,这句话本身是错误的,tcp是协议,发送接收数据时并不会粘包,tcp,ip,只负责传输数据
粘包是应用层解析数据时,包1和包2粘连在一起,解析数据时,出现错误的,网络中,很多博主,就没搞清楚。

send,发送频率太快,发送包的时候,有可能发送1400字节,或100个字节,按流的方式发送,应用层很快频率,非阻塞去recv数据时,不一定能读到1400个字节,可能只有1000个,下次再去读取时,读到应用层发送的第一包里的后400个字节开头的数据包,出现粘包,解析数据头是出错,其实tcp传输数据时,没有包的概念,和uart串口一样,只有流的概念,tcp协议讲的很清晰,tcp是面向流的,一个一个字节流,
tcp传输时,只按流的方式发送,没有一包一包的概念,假如发送数据很大,tcp协议,自动分成多包一个一个字节进行发送,接收端接收到数据,会自动按包号,进行组合假如分成1,2,3,4,5包,接收端接收到1,2,4,5,底层协议自动组合,错误将自动重传,所以,tcp是可靠的传输。

这个包和应用层send发包不是一个概念,udp才是面向报文的,应用层按包发送接收,发送1400字节的包,udp只要网络正常,基本一定能收到1400个字节的包,tcp不一定能recv能接收到1400个字节,所以如果用结构,去解析包头,数据段的数据,这时候,有可能就回错误,包头校验不对,如下一段代码,用结构类型去解析接收buf的数据,注意,我这里qt的read接收的,linux是recv。

	PT_udpSocketDataPkt _tDataPkt1 = (PT_udpSocketDataPkt)this->databufer2;
	memset(_tDataPkt1, 0, sizeof(T_udpSocketDataPkt));

	int rcvlen = ClientTcpSocket->read((char*)_tDataPkt1, UDP_MAX_LEN);//最多读1400个
	if(rcvlen <= 0)
	{
	    QMessageBox::information(this, CCODE("提示"), CCODE("接收服务端数据失败!"));
	}
	else if ( ( (rcvlen >= UDP_MIN_LEN) && (rcvlen <= UDP_MAX_LEN) )  \
	&& (_tDataPkt1->DataHead.u32Sync == PKT_SYNC) && (_tDataPkt1->DataHead.u8Cmd = CMD_SNAP_PIC_CMD_ACK))
	{
		if (_tDataPkt1->DataHead.u16TotalPktNum != _tDataPkt1->DataHead.u16CurrentPktSn)//接收到一包数据
		{
		}
	}
			

如果服务端发数据够快,客服端读取数据时,就可能解析不对,也是被udp干扰了,写udp时,就是按包发送,接收,去解析的,没问题。
放到tcp就有可能有问题。
csdn很多博主,在解决粘包问题时,其中解决方法,是这样建议的,没有考虑这个问题,什么极端情况都可能出现的。

tcp应用层解析数据时,发送大量数据,很有可能会出现这样情况,上面的方法其实也可以在某系业务时可用,如发送频率较慢,几ms发送数据,接收端慢一点,能及时处理读取全部数据,并且回复发送端,收到已处理消息,接收端再发送,就可以这样,但是发送数据很慢,传输一个几mb的文件,很慢,这样用udp协议也可以了,就没必要用tcp了,tcp就是可靠。

如果是传输大文件时,只需发送方告诉接收方,文件的大小,接收按流的方式读取到buf里,recv多少个字节,就放到buf里,直到收完大小为止,后者,很多人建议的。
如果事先不知道文件大小,也可以这样做,在数据里,加结束标志如\\\,读到包结束标志后,表示完整包发送完毕。

需要处理大量数据时,最好还是按流的方式处理数据,放到buf里,如果数据是报文,消息,可以加标志位,应用层根据结束标志位,在流buf里,寻找一个完整的包,如果是连续的文件,接收多少个字节,就按多少个字节拼接到buf里。


http://www.niftyadmin.cn/n/883427.html

相关文章

【ITK】最短路径提取

【ITK】最短路径提取 有一个寻找最短路径的需求,搜索后发现这篇文章 Fast Marching Minimal Path Extraction in ITK (https://www.insight-journal.org/browse/publication/213) 开源的作者08年写的&#xff0c;2019这个项目在git上还有更新。 作者使用了梯度下降和正阶梯度…

IIC时序和linux驱动框架剖析

作者原地址&#xff0c; https://www.cnblogs.com/alantu2018/p/8994719.html 博客园Logo 首页 新闻 博问 专区 闪存 班级 代码改变世界 搜索 注册 登录 AlanTu 随笔 - 952, 文章 - 0, 评论 - 47, 阅读 - 215万 对 IIC 总线的理解、调用函数以及常见面试问题 一、IIC 总线概述…

hisi35xx保存yuv图片调试

hisi系列&#xff0c;yuv保存结构体&#xff0c; u64PhyAddr[3]是申请一个结构体类型时&#xff0c;分配的一个物理地址&#xff0c;当保存一帧图片到这个结构体时 这帧图片分配的一端内存首地址&#xff0c;就放在这里&#xff0c;需要读取图片数据时&#xff0c;需要向内核&a…

QGraphicsView QGraphicsScene 增加任意点

这玩意信号传递是 view —scene—item 一旦把事件重构了了&#xff0c;一定要每个事件处理后 QGraphicsItem::mouseMoveEvent(event); 有跟我一样需求的可以看下我的&#xff0c; 增加任意点&#xff0c;点的顺序可以改变 每个点可以拖动和wasd移动 每个任意点的位置实时显示 …

hisi3559av100,MIPI相机输入接口调试

hisi3559av100&#xff0c;MIPI相机输入接口调试&#xff0c;后期有空写

【OpenCV】ubuntu下show报错

编译opencv之前没有安装 libgtk2.0-dev sudo aptinstall libgtk2.0-dev cd "opencv_release_path" cmake make -j12 sudo make install

qt cmake 配置模板

cmake常用指令很少 cmake_minimum_required(VERSION major.minor[.patch[.tweak]] [FATAL_ERROR]) 指定构建工程时所需要的版本要求。 VERSION必须关键字 指最低要求major.minor[.patch[.tweak]] 可选关键字 指定使用哪一个版本FATAL_ERROR 可选关键字&#xff0c;如果版本不…

扩展芯片,hisi3559av100 i2c调试

扩展芯片&#xff0c;hisi3559av100 i2c调试&#xff0c;后期有空写