一个通用网络协议数据解析

Posted 西北老码农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个通用网络协议数据解析相关的知识,希望对你有一定的参考价值。

1、网络数据解析

我们在实际应用中,网络数据解析是非常常见的一种数据处理方式,那么有没有比较通用的数据解析处理方法呢,以下是个人总结的一种网络数据解析处理方法

2、数据包格式

      图1-1是一个比较通用的数据包格式,本次数据解析模型以下图的数据格式为准:

3、代码实现

int ReceiveFromRemoteEndPoint()
     
    int nPackageDataLength = 0; 
    char *szPackageCleaner = NULL;
    char *szPackageIterator = NULL;
    do 
    
        char *szReceiveArray = new char[RECEIVED_BUFFER_LENGTH]();
        int nReceiveLength = RECEIVED_BUFFER_LENGTH; 
        nReceiveLength = Receive(szReceiveArray, nReceiveLength, TIMEOUT);
        if (nReceiveLength <= 0)
        
            Log("Recveived Time-Out(%d)...", nReceiveLength);   
            delete[] szReceiveArray;
            break;
        
        Log("Received (%d) Bytes", nReceiveLength);  
        char *szReceive = szReceiveArray;
        do 
        
            if(nPackageDataLength == 0)
             
                if(szReceive[0] != HEADER) 
                
                    Log("Package Data Header-Analysis Error, Size(%d).", nReceiveLength); 
                    break;  
                
                if(nReceiveLength < PACKHEADERLENGTH)
                
                    Log("Package Data Length-Analysis Error, Size(%d).", nReceiveLength); 
                    break;   
                

                //offset HEADER length
                char *szPackageDataLength = szReceive + sizeof(char);
                //包数据的长度(不包含包头长度)
                LengthResolve(szPackageDataLength, nPackageDataLength); 

                szPackageCleaner = new char[nPackageDataLength + PACKHEADERLENGTH + 1]();
                szPackageIterator = szPackageCleaner;

                memcpy(szPackageIterator, szReceive, PACKHEADERLENGTH);
                szPackageIterator += PACKHEADERLENGTH;

                szReceive += PACKHEADERLENGTH;
                nReceiveLength -= PACKHEADERLENGTH;
             
            //已接收的包数据长度 < 包数据长度 = 一个不完整的包 
            if(nReceiveLength < nPackageDataLength)
               
                memcpy(szPackageIterator, szReceive, nReceiveLength);
                szPackageIterator += nReceiveLength;
                nPackageDataLength -= nReceiveLength;

                szReceive += nReceiveLength;
                nReceiveLength -= nReceiveLength;
            
            else//(nReceiveLength >= nPackageDataLength)
            
                //已接收的包数据长度 == 包数据长度 = 一个完整的包  
                //已接收的包数据长度 > 包数据长度  = 至少有一个完整的包 + 至少一个数据片段 
                memcpy(szPackageIterator, szReceive, nPackageDataLength);
                //szPackageIterator += nPackageDataLength;
                Resolve(szPackageCleaner, (szPackageIterator - szPackageCleaner) + nPackageDataLength);
                szReceive += nPackageDataLength;
                nReceiveLength -= nPackageDataLength;
                nPackageDataLength = 0;

                delete[] szPackageCleaner;
                szPackageCleaner = NULL; 
                        
        while(nReceiveLength > 0);    
        delete[] szReceiveArray;
        Sleep(8);

    while(IsStop);//Receiving
    
     if(szPackageCleaner != NULL)
        delete[] szPackageCleaner;
    
    return 0;

 4、超时或者异常上报机制

增加超时和异常上报。

5、数据包处理注意事项

if(nReceiveLength < PACKHEADERLENGTH)

     Log("Package Data Length-Analysis Error, Size(%d).", nReceiveLength);

    //这里会出现些问题

break;

       假如一个完整的数据包解析后,剩余的接收长度 < PACKHEADERLENGTH, 即包头HEADER校验正确,但是解析包数据长度的时接收到的数据不足以解析出数据要接收的长度。此策略会丢弃包数据至下一个正确的包被正确解析,这个和缓冲区设置的长度是没有直接关系的,当然长度要大于PACKHEADERLENGTH。要解决这个问题,可以在 break; 之前保存这个数据片,并在和下次接收的拼接解析数据长度。

以上是关于一个通用网络协议数据解析的主要内容,如果未能解决你的问题,请参考以下文章

DNS解析污染原理——要么修改包,要么直接丢弃你的网络包

在http协议中post表单 发现由于包被分片 但是用wireshark查看的时候每一个IP分片包 df标志位却为1?

TFTP协议中的旧重复数据包

网络通信

通用路由封装(GRE)

计算机网络——网络层02