一個C++版的網絡數據包解析策略


 

C++版的網絡數據包解析策略(升級版)

一、數據包格式形如下圖

二、代碼

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;
} 

三、說明

網絡數據包接收,最好是有超時機制的,比如2秒左右。

if(nReceiveLength < PACKHEADERLENGTH)
{
         Log("Package Data Length-Analysis Error, Size(%d).", nReceiveLength);
         //這里會出現些問題 
         break;   
}

問題描述:
  假如一個完整的數據包解析后,剩余的接收長度 < PACKHEADERLENGTH, 即包頭HEADER校驗正確,但是解析包數據長度的時接收到的數據不足以解析出

數據要接收的長度。此策略會丟棄包數據至下一個正確的包被正確解析,這個和緩沖區設置的長度是沒有直接關系的,當然長度要大於PACKHEADERLENGTH.

要解決這個問題,可以在 break; 之前保存這個數據片,並在和下次接收的拼接解析數據長度。

此策略不是最好的更不是最優的,更好的可能就在你那里呢,有你的指點我相信會更好的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM