tcp 粘包 丢包 解决方案

news/2024/5/17 17:39:03 标签: 粘包, 丢包, tcp

1、分析tcp粘包丢包的原因

   发送数据的时候有  发送缓冲区senBuff,

   接收数据的时候有  接收缓冲区recvBuff,

   假如接收数据方一直不recv, 则recvBuff就会堆满, 这个时候tcp就会停止发送数据了。

   同样因为接收缓冲区的数据满了, 所以发送缓冲区也不会再就收发送方发来的消息。

2、解决方案

// 接收数据  处理年包 拆分包
int CEasyTcpClient::RecvData()
{
	//char szRecv[1024] = {};
	printf("RecvData, 11111");
	// 5 接收客户端请求
	int nLen = (int)recv(m_sock, m_szRecv, RECV_BUFF_SIZE, 0);
	if (nLen <= 0)
	{
		printf("<socket = %d>与服务器断开连接, 任务结束。 \n", (int)m_sock);
		return -1;
	}

	printf("client recv data , nLend = %d\n", nLen);

	//将收取到的数据拷贝到消息缓冲区
	memcpy(m_szMsgBuf + m_nLastPos, m_szRecv, nLen);
	//消息缓冲区的数据尾部位置后移
	m_nLastPos += nLen;
	//判断消息缓冲区的数据长度大于消息头DataHeader长度
	while (m_nLastPos >= sizeof(DataHeader))
	{
		//这时就可以知道当前消息的长度
		DataHeader* header = (DataHeader*)m_szMsgBuf;
		//判断消息缓冲区的数据长度大于消息长度
		if (m_nLastPos >= header->dataLength)
		{
			//消息缓冲区剩余未处理数据的长度
			int nSize = m_nLastPos - header->dataLength;
			//处理网络消息
			OnNetMsg(header);
			//将消息缓冲区剩余未处理数据前移
			memcpy(m_szMsgBuf, m_szMsgBuf + header->dataLength, nSize);
			//消息缓冲区的数据尾部位置前移
			m_nLastPos = nSize;
		}
		else {
			//消息缓冲区剩余数据不够一条完整消息
			break;
		}
	}
	return 0;
}

类似这样的大概思路就是  接收到数据存到一级缓冲区, 然后从一级缓冲区拷贝到二级缓冲区, 之后判断二级缓冲区长度是否大于包头长度, 如果大于包头长度就进行解析,  因为包头里面包含了完整消息协议的总长度。  这样就不会出现粘包丢包的问题了。


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

相关文章

CMake 生成makefile 步骤

1、首先创建一个目录下的makefile //main.cpp #include<iostream> using namespace std; int main() {cout<<"Hello word!"<<endl;return 0; }在main文件所在的目录创建CMakeLists.txt //CMakeLists.txt PROJECT(main) CMAKE_MINIMUM_REQUIRED(V…

PE结构(DOS,NT,SectionHeader 不含 DataDirectory)一

PE结构&#xff1a;所有的可执行文件都要满足PE文件建构 我这里就以内存图的形式展示一下pe结构 上图为pe的简单内存结构图 1.DosHeader 结构 这里我仅说明我常用到的成员。 struct _IMAGE_DOS_HEADER { 0x00 WORD e_magic; // 记录是否是可执行文件 0x02 W…

hadopp 环境搭建

我的配置 我在虚拟机中设置了三个实例&#xff0c;以下是它们的名字 s1&#xff1a;master s2&#xff1a;slaves3&#xff1a;slave 虚拟机的网络配置 配置固定 IP vi /etc/network/interfaces auto eth0 iface eth0 inet static address 192.168.191.128 netmask 255.25…

hadoop 的命令

维护的命令 start-all.sh/stop-all.sh&#xff1a;启动/关闭所有&#xff0c;包括 nodeName、dataNode、secordaryNode、resourcManage(yarn)&#xff0c;不过&#xff0c;这两个命令已经废弃了&#xff0c;所谓长江后浪推前浪&#xff0c;下面来看一下新秀命令stop-dfs.sh/st…

自动运维的脚本分析

发现的脚本 boot_all.sh 下面的脚本完成了两个任务 将脚本执行机器对其他的服务器免登陆将 install.sh 脚本复制到其他的服务器&#xff0c;并且执行 #!/bin/bashSERVERS"$1" PWD123 BASE_SERVERserver1auto_ssh_copy_id(){expect -c "set timeout -1;// ex…

多线程实现互斥访问对象的方法

场景说明 假设有 A、B 两个线程都去调用对象 α 的方法 method1(),并且要求 A、B 两个线程是互斥调用 method1 的。具体来说&#xff0c;假设 method1 中有 4 个命令&#xff0c;一旦 A 调用了 method1&#xff0c;在执行 method1 中有 4 个命令的时候&#xff0c;B 不会调用 …

HDFS 架构官文理解

HDFS 使命 实现硬件级别的容错提供数据流方式的访问文件提供超大数据量的存储&#xff0c;GB、TB、PB&#xff0c;这其中还包含了访问速度的要求。实现简单的一致性&#xff0c;为了保证整个集群里面不同副本之间的数据是一致的&#xff0c;所以 HDFS 只之支持了文件简单的文…

自己封装的MR类

简介 自己在练习 MR 的时候&#xff0c;重复的操作的代码比较多&#xff0c;于是灵机一动&#xff0c;自己何不写一个代理类&#xff0c;把 Maper、reducer、partitioner 等方法封装到一起。 所以就有了下面这个类。 MR 代理类 自己写的 MR 的代理类&#xff0c;能给自己省…