zoukankan      html  css  js  c++  java
  • 一个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; 之前保存这个数据片,并在和下次接收的拼接解析数据长度。

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

  • 相关阅读:
    内网或无域名服务器集成微信公众号接口
    记录一次重新学习SetInternal和SetTimeout
    SQLServer日志过大导致还原失败的解决方案
    批量修改SQLServer数据库表字段属性
    收缩SQLServer数据库解决日志占用空间过大(2008R2以上版本)
    SAP GUI安装出现ocx错误提示的解决办法
    .NetCore自动转换枚举类显示自定义中文名称
    EFCore-脚手架Scaffold发生Build Failed问题的终极解决
    .NetCore自定义WebAPI返回Json的格式大小写的三种方式
    存储过程模糊搜索,按匹配率排序初探
  • 原文地址:https://www.cnblogs.com/wjshan0808/p/6580638.html
Copyright © 2011-2022 走看看