TCP粘包和半包的处理方法

先把处理的方法的代码放这里:

解析数据帧的代码:

bool CSocket::findData(byte* buff, int& len)
{

	for (int i = 0; i <= len - 4; i++)
	{
		int dataLen;
		if(buff[i] == 0xAA && buff[i + 1] == 0xBB)
		{
			short slen;
			slen = (short)(byte(buff[i+3]));
			slen |=(short)((short)(byte(buff[i+2])) << 8);
			dataLen = slen;
			if(slen < 0)
				return false;

			if(i+4 +dataLen + 4 <= len)
			{
				if(buff[i + 4 + dataLen] == 0x0DD && buff[i + 4 + dataLen + 1] == 0xEE && buff[i + 4 + dataLen + 2] == 0xDD && buff[i + 4 + dataLen + 3] == 0xEE)
				{
					MsgType type;
					memcpy(&type, buff + i + 4 , sizeof(type));

					if(type == ID_LASER)
					{}
					else if(type == ID_PATH)
					{}
					else if(type == ID_POSE)
					{}
					len = len - i - 4 - dataLen - 4;
					if( len > 0)
					{
						memcpy(swapBuff, buff + i + 4 + dataLen + 4, len);
						memcpy(buff, swapBuff, len);
					}
					return true;
				}
				else
				{
					len = len - i -4;
					if(len > 0)
					{
						memcpy(swapBuff, buff + i + 4, len);
						memcpy(buff, swapBuff, len);
						return false;
					}
				}
			}//if
			else if(i != 0)
			{
				len = len - i;
				memcpy(swapBuff, buff + i, len);
				memcpy(buff, swapBuff, len);
				return false;
			}
		}//if
	}//for

	return false;
}//end function

  

接收数据帧的代码:

void CSocket::receiveData()
{
  ROS_INFO("Receive Thread Start...");

	int len =0;
	int revDateCount = 0;
  while(bRunning)
  {
    if(!connected)
    {
        ROS_INFO("Restarting connection...");
		ErroFunc(_T("连接中断,尝试重新连接..."));

        if(serverSocket > 0)
        {
          closesocket(serverSocket);
          serverSocket = -1;
        }

        if(clientSocket > 0)
        {
          closesocket(clientSocket);
          clientSocket = -1;
        }

        bool re;
        if(bServer)
          re = startServer();
        else
          re = connectServer();
        if(!re)
            continue;
		revDateCount = 0;
		MsgFunc(_T("连接到机器人!"));
    }

    int re = selectSocket(clientSocket, 500);
    if(re < 0)
    {
      ROS_ERROR("Receive Thread Select Error!");
      connected = false;
      continue;
    }
    else if(re == 0)
      continue;
    else
    {
      len  = recv(clientSocket, (char*)recvBuffer, MAX_BUFFER_LEN, 0);
      if(len > 0)
      {
		if(revDateCount + len < MAX_BUFFER_LEN)
		{
			memcpy((void*)(buff + revDateCount), (void*)recvBuffer, len);
			revDateCount += len;
		}
		else
		{
			memcpy((void*)buff, (void*)recvBuffer, len);
			revDateCount = len;
		}

		while(findData(buff, revDateCount))
		{
			ROS_INFO("Receive data!");
		}
      }
	  else
      {
        ROS_ERROR("Receive Data Error!");
        connected = false;
        goto __reconnect__;
	  }
	}
    __reconnect__:;
  }
  ROS_INFO("Receive Thread Stop.");
}

  

时间: 2024-10-11 23:39:43

TCP粘包和半包的处理方法的相关文章

SOCKET TCP 粘包及半包问题

大家在使用SOCKET通信编程的时候,一般会采用UDP和TCP两种方式:TCP因为它没有包的概念,它只有流的概念,并且因为发送或接收缓冲区大小的设置问题,会产生粘包及半包的现象. 场景: 服务端向连续发送三个"HelloWorld"(三次消息无间隔),那么客户端接收到的情况会有以下三种: 1)HelloWorld HelloWorld HelloWorld (客户端接收三次) 2)HelloWorldHelloWor ldHelloWorld (客户端接收两次) 3)HelloWorl

关于TCP封包、粘包、半包

关于Tcp封包 很多朋友已经对此作了不少研究,也花费不少心血编写了实现代码和blog文档.当然也充斥着一些各式的评论,自己看了一下,总结一些心得. 首先我们学习一下这些朋友的心得,他们是: http://blog.csdn.net/stamhe/article/details/4569530 http://www.cppblog.com/tx7do/archive/2011/05/04/145699.html //……………… 当然还有太多,很多东西粘来粘区也不知道到底是谁的原作,J 看这些朋友

socket编程 粘包和半包 问题的及处理

一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次可能会来 0.5/1 /2/ 2.5/ ....个包 当接收到时 要先看看那这个包中有多少个完整的包.把完整的包都处理了 也就是说把x都处理了.剩下的0.5留在接收区中,等待下次接收. 这回接收到的就是0.5+1.5/0.5+1.3/0.5+0.5..... 把完整的包都处理了,有残缺的扔掉 0.8

C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)

介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解决Socket粘包.半包问题. 更甚至,某些师德有问题的老师,根本就没跟你说过Socket的粘包.半包问题是什么玩意儿. 直到有一天,你的Socket程序在传输信息时出现了你预期之外的结果(多于的信息.不完整的信息.乱码.Bug等等). 任你喊了一万遍“我擦”,依旧是不知道问题出在哪儿! 好了,不说

c# socket 解决粘包,半包

处理原理: 半包:即一条消息底层分几次发送,先有个头包读取整条消息的长度,当不满足长度时,将消息临时缓存起来,直到满足长度再解码 粘包:两条完整/不完整消息粘在一起,一般是解码完上一条消息,然后再判断是否有剩余字节,有的话缓存起来,循环半包处理 客户端接收代码: private void callReceived(object sender, SocketAsyncEventArgs args) { var socket = sender as Socket; var bb = args.Use

【转载】socket的半包,粘包与分包的问题

http://zhaohuiopensource.iteye.com/blog/1541270 首先看两个概念: 短连接: 连接->传输数据->关闭连接    HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.    也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接. 长连接: 连接->传输数据->保持连接 -> 传输数据-> ... ->关闭连接. 长连接指建立SOCKET连接后不管是否使用都

Java 粘包/半包 原理与拆包实战(史上最全)

疯狂创客圈 Java 聊天程序[ 亿级流量]实战系列之13 [博客园 总入口 ] 本文的源码工程:Netty 粘包/半包原理与拆包实战 源码 本实例是<Netty 粘包/半包原理与拆包实战> 一文的源代码工程. 写在前面 大家好,我是作者尼恩. 为了完成了一个高性能的 Java 聊天程序,在前面的文章中,尼恩已经再一次的进行了通讯协议的重新选择. 这就是:放弃了大家非常熟悉的json 格式,选择了性能更佳的 Protobuf协议. 在上一篇文章中,并且完成了Netty 和 Protobuf协议

TCP粘包/拆包问题

无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包/拆包 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. TCP粘包/拆包问题说明 假设客户

Netty(三)TCP粘包拆包处理

tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D2给服务端,由于服务端一次性读取到的字节数是不确定的,所以可能存在以下4种情况. 1.服务端分2次读取到了两个独立的包,分别是D1,D2,没有粘包和拆包: 2.服务端一次性接收了两个包,D1和D2粘在一起了,被成为TCP粘包; 3.服务端分2次读取到了两个数据包,第一次读取到了完整的D1和D2包的部