处理TCP连包的一小段代码
学习网络编程也有一段时间了,一直听说TCP数据会连包,但一直不知道怎么测试好。最近测试了下:发送方使用对列,将发送的数据存入队列,然后开线程,专门发送。发送多包数据之间不延时。在接收方,他们确实连在一起了。花了点时间,写了一小段代码解决这个问题,其实一共也就4个函数:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #define FIND_NO_HEAD 1024 2 3 int MyTcpSock::GetPackageSetedLength(char *pHeader) 4 { 5 XX_NETPACKET_HEADER *pNetHeader = (XX_NETPACKET_HEADER *)pHeader; 6 7 return (sizeof(XX_NETPACKET_HEADER) + pNetHeader->packetsize); 8 } 9 10 int MyTcpSock::FindHeaderFlag(char *buf,int len) 11 { 12 #define FLAGS_NUM 4 13 14 int count = 0; 15 char i=0; 16 unsigned char Flags[FLAGS_NUM] = {XX_FLAG1,XX_FLAG2,XX_FLAG3,XX_FLAG4}; 17 XX_NETPACKET_HEADER *pHeader = (XX_NETPACKET_HEADER *)(buf+count); 18 19 while(count < len) 20 { 21 for(i=0;i<FLAGS_NUM;i++) 22 { 23 if(pHeader->flag == Flags[i]) 24 { 25 return ((char *)pHeader - buf); 26 } 27 } 28 29 count ++; 30 pHeader = (XX_NETPACKET_HEADER *)(buf+count); 31 } 32 33 return FIND_NO_HEAD; 34 } 35 36 void MyTcpSock::ResolveRecievedData(char *buf,int len) 37 { 38 char *pUnreslovedData = (char *)buf; //指向待解析的数据的开始 39 int iUnreslovedDataLen = len; //待解析的数据的长度 40 int iHeaderPosition = 0; //数据头的位置--相对于待解析的数据的起始位置 41 int iPackageLen = 0; //解析出的命令的数据包长度 42 43 while(iUnreslovedDataLen > 0) 44 { 45 iHeaderPosition = FindHeaderFlag(pUnreslovedData,iUnreslovedDataLen); 46 if(iHeaderPosition == FIND_NO_HEAD) 47 { 48 TRACE("Find no Header!\n"); 49 Printf(pUnreslovedData,iUnreslovedDataLen); 50 return ; 51 } 52 iPackageLen = this->GetPackageSetedLength((char *)(pUnreslovedData+iHeaderPosition)); 53 if(iPackageLen > iUnreslovedDataLen) 54 { 55 TRACE("Package is not full!\n"); 56 Printf(pUnreslovedData,iUnreslovedDataLen); 57 return ; 58 } 59 60 ResolvePackageCmd((char *)(pUnreslovedData+iHeaderPosition),iPackageLen); 61 62 pUnreslovedData = pUnreslovedData + iHeaderPosition + iPackageLen; //调整指针 63 iUnreslovedDataLen = iUnreslovedDataLen - iHeaderPosition - iPackageLen; 64 } 65 } 66 67 void MyTcpSock::ResolvePackageCmd(char *buf,int len) 68 { 69 XX_NETPACKET_HEADER *pNetHeader = (XX_NETPACKET_HEADER *)buf; 70 71 //XXX后面就是命令的解析了 72 }
以上代码是C++,去掉类就是C。以上代码经过测试,可以解决如下问题:
数据连包的问题。
数据发送丢失,比如有包头却丢失了一些数据。后面解析这些命令时,如果以为数据存在,直接用将会出现不可预知的错误。
命令包格式的设计,基本要遵守CLV的格式,C-code命令,L-Length命令长度,V-Value值。
这里的命令也基本上就是上面的Flag,因为不通命令可能带的值不一样,所以也就必须定义此命令的长度。这在连包处理上非常重要。