处理TCP连包的一小段代码

  学习网络编程也有一段时间了,一直听说TCP数据会连包,但一直不知道怎么测试好。最近测试了下:发送方使用对列,将发送的数据存入队列,然后开线程,专门发送。发送多包数据之间不延时。在接收方,他们确实连在一起了。花了点时间,写了一小段代码解决这个问题,其实一共也就4个函数:

 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 }
View Code

  以上代码是C++,去掉类就是C。以上代码经过测试,可以解决如下问题:

  数据连包的问题。

  数据发送丢失,比如有包头却丢失了一些数据。后面解析这些命令时,如果以为数据存在,直接用将会出现不可预知的错误。

      命令包格式的设计,基本要遵守CLV的格式,C-code命令,L-Length命令长度,V-Value值。

  这里的命令也基本上就是上面的Flag,因为不通命令可能带的值不一样,所以也就必须定义此命令的长度。这在连包处理上非常重要。

posted @ 2015-12-11 14:37  kanite  阅读(480)  评论(0编辑  收藏  举报