c++ TCP协议分包

前言

    TCP是一种流式协议,存在粘包的现象,所以需要分包处理。

数据包格式

    不同格式的数据包的分包方法也不相同,本文使用的格式为:

                    #长度,包头:数据内容@

    其中,长度是从包头到数据内容总字节数,4位定长

代码

void RecvThread::run()
{
	char buffer[2048] = {0};    // 用于存放读取到的数据
	char *buf = buffer;         //
	int len = 0;                // TCP通信读取到的数据长度
	int bufferLen = 0;          // 当前数据长度
	int needLen = 0;            // 还需要读取的数据长度

	while(m_tcpConnectionClient->isOpen())
	{
		memset(buffer, 0, 2048);

                // 查找开始标志
		while(buf[0] != '#')
		{
			needLen = 1 - bufferLen < 0 ? 0 : 1 - bufferLen;
			if (needLen == 0)
			{
				bufferLen -= 1;
				memmove(buf, buf + 1, bufferLen);
				memset(buf + bufferLen, 0, 2048 - bufferLen);
			}
			else
			{
				len = m_tcpConnectionClient->read(buf, needLen);
				if (len < 0)
				{
					break;
				}
			}
		}

		if (len < 0)
		{
			break;
		}

                // 读取长度
		bufferLen += needLen;
		needLen = 6 - bufferLen < 0 ? 0 : 6 - bufferLen;
		len = m_tcpConnectionClient->read(buf + 1, needLen);
		if (len < 0)
		{
			break;
		}

		bufferLen += needLen;
		if (buf[5] == ',')
		{
			char cLen[5] = {0};
			cLen[0] = buf[1];
			cLen[1] = buf[2];
			cLen[2] = buf[3];
			cLen[3] = buf[4];
			int dataLen = atoi(cLen);
			if (dataLen > 0 && dataLen < 2000)// 至此判断为完整的头
			{
				needLen = dataLen + 7 - bufferLen < 0 ? 0 : dataLen + 7 - bufferLen;
				len = m_tcpConnectionClient->read(buf + 6, needLen);
				if (len < 0)
				{
					break;
				}

				bufferLen += needLen;
				if (buf[dataLen + 6] == '@')
				{
					string str = "";
					str.assign(buffer, dataLen + 7);
					gotMsg(str);

					bufferLen -= dataLen + 7;
					memmove(buf, buf + dataLen + 7, bufferLen);
					memset(buf + bufferLen, 0, 2048 - bufferLen);

					continue;
				}
			} 
		} 

		bufferLen -= 1;
		memmove(buf, buf + 1, bufferLen);
		memset(buf + bufferLen, 0, 2048 - bufferLen);
	}
}

说明

    1. TCPConnectionClient *m_tcpConnectionClient是自定义的TCP通信的类,其read函数使用while循环读取数据,直到读取到指定的数据长度;

    2. memmove用于内存发生局部重叠的时候,保证拷贝结果是正确的;

    3. gotMsg(str)用于处理分出来的单个数据包;

    4. 代码逻辑并不十分清晰和严密,欢迎指正。

你可能感兴趣的:(c++ TCP协议分包)