一 简述
在应用程序中,有时需要存储主机端口并根据相应条件判断某些端口是否在存在。比如snort插件代码中,会根据输入包的端口与配置文件snort.conf里读取的的端口进行匹配操作。如果存储所有的主机端口将浪费一定存储空间,因此,可以设计一种简易的端口存储方式,即可节省存储空间,又能快速识别端口。
二 思路分析
1.设计一个一维数组ports,其长度是MAX_PORTS(65536)/8;
2.某一个端口port在ports的索引是port/8,比如端口8,9,10...15都被存储到ports[1];
3.端口port在ports的值是原值 | (1 << port%8),比如端口8,9,10...15都被存储到ports[1],而ports[1]最后值为11111111。
三 代码
1.单例single_instance.hpp:
#pragma once
template <class T>
class single_instance {
public:
static inline T& instance() {
static T obj;
return obj;
}
private:
single_instance() = default;
virtual ~single_instance() = default;
};
2.ports_storage_utility.hpp:
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "single_instance.hpp"
class ports_storage_utility {
public:
inline void store(uint32_t port) {
ports[port_index(port)] |= port_map(port);
}
inline bool valid(uint32_t port) {
return port > 0 && port < MAX_PORTS;
}
inline bool existed(uint32_t port) {
return ports[port_index(port)] & port_map(port);
}
inline void clear() {
memset(ports, 0, sizeof(ports));
}
private:
inline uint16_t port_index(uint32_t port) {
return port / 8;
}
inline uint8_t port_map(uint32_t port) {
return 1 << (port % 8);
}
private:
static const int MAX_PORTS = 65536;
uint8_t ports[MAX_PORTS / 8] = { 0 };
};
#define G_PORTS_STORAGE_UTILITY single_instance<ports_storage_utility>::instance()
3.编译make.sh:
g++ -std=c++11 -g -o Test test.cpp -I ./
4.测试test.cpp
#include <iostream>
#include "ports_storage_utility.hpp"
int main() {
G_PORTS_STORAGE_UTILITY.store(2889);
G_PORTS_STORAGE_UTILITY.store(78);
G_PORTS_STORAGE_UTILITY.store(3);
std::cout << G_PORTS_STORAGE_UTILITY.existed(2889) << std::endl;
std::cout << G_PORTS_STORAGE_UTILITY.existed(78) << std::endl;
std::cout << G_PORTS_STORAGE_UTILITY.existed(3) << std::endl;
std::cout << G_PORTS_STORAGE_UTILITY.existed(300) << std::endl;
return 0;
}
https://github.com/wangzhicheng2013/common_utility