代码之家  ›  专栏  ›  技术社区  ›  Samo Poláček

映射同一索引的不同键

  •  0
  • Samo Poláček  · 技术社区  · 7 年前

    在进行重构时,我不知何故把代码搞砸了,所以我使用的std::map停止了正常工作。

    我正在重新组装碎片化的IPv4数据包。 部分解析 Packet 如果它是数据包的一部分,它就会变成 Fragment 具有重新组装功能。

    ...    
    if(packet.isIPv4() && packet.isFragment()){
        auto keyForMap = packet.key();
        auto it = fragments.find(keyForMap);
        auto fragmentNotFound = fragments.end();
    
        std::cout << "-----------------------"  << std::endl;        
        std::cout << "Fragments len: " << fragments.size() << std::endl;        
    
        keyForMap.print();
    
        if(it == fragmentNotFound){
            std::cout << "Not Found" << std::endl;
            fragments[keyForMap] = Fragment(packet);
        } else {
            std::cout << "Found" << std::endl;
    
            fragments[keyForMap].add(packet);
            /* reassembling function call and some processing */
            }
        }
    }
    ...
    

    使用的数据类型: IPv4 std::array<uchar_t, 4>

    fragments fragments_t &

    fragments_t std::map<FragmentCommon, Fragment>

    struct FragmentCommon{
        FragmentCommon(IPv4 ipsrc,
                       IPv4 ipdst,
                       uchar_t protocol,
                       uint16_t identification) : ip_src(ipsrc),
                                                  ip_dst(ipdst),
                                                  protocol(protocol),
                                                  identification(identification){};
    
        void print(){
            printf("key>%d.%d.%d.%d ", ip_src[0], ip_src[1], ip_src[2], ip_src[3]);
            printf("%d.%d.%d.%d ", ip_dst[0], ip_dst[1], ip_dst[2], ip_dst[3]);
            printf("%d %d\n", protocol, identification);
        };
    
        IPv4 ip_src;
        IPv4 ip_dst;
        uchar_t protocol;
        uint16_t identification;
    };
    
    static bool operator<(const struct FragmentCommon &lhs, const struct FragmentCommon &rhs){
        return lhs.ip_dst         < rhs.ip_dst &&
               lhs.ip_src         < rhs.ip_src &&
               lhs.protocol       < rhs.protocol &&
               lhs.identification < rhs.identification;
    }
    

    这是我的代码给我的输出:

    -----------------------
    Fragments len: 0 // Correct (this is first fragment so nothing is in map)
    key>192.168.1.3 192.168.1.4 6 1
    Not Found // So it's added into map
    -----------------------
    Fragments len: 1 // Correct (1st fragment is in map)
    key>192.168.1.5 192.168.1.6 6 1
    Found // Not correct...keys are different
    -----------------------
    Fragments len: 1
    key>192.168.1.5 192.168.1.6 6 1
    Found
    -----------------------
    Fragments len: 1
    key>192.168.1.5 192.168.1.6 6 1
    Found
    -----------------------
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   PaulMcKenzie    7 年前

    考虑到你在问题中发布和陈述的内容,自 IPv4 std::array<uchar_t,4> (我假设 uchar_t 是的别名 unsigned char operator < 对于 FragmentCommon 使用 std::tie .

    使用 std::tie 对于定义 (对于 std::map 键)以“级联”方式处理要测试的多个值时。

    #include <tuple>
    //...
    static bool operator < (const struct FragmentCommon &lhs, const struct FragmentCommon &rhs)
    {
        return std::tie(lhs.ip_dst, lhs.ip_src, lhs.protocol, lhs.identification) < 
               std::tie(rhs.ip_dst, rhs.ip_src, rhs.protocol, rhs.identification);
    }
    

    std::array has operator < 定义,使用 标准::tie 在每个参数中使用全部4个参数时正确工作 标准::tie .