对于我的服务器应用程序,我需要检查一个IP地址是否在我们的黑名单中。
比较IP地址的最有效方法是什么?将IP地址转换为整数并将它们比较有效吗?
答案 0 :(得分:28)
取决于您正在使用的语言,但IP地址通常存储为32位无符号整数,至少在网络层存储,使得比较速度非常快。即使不是这样,除非您正在设计高性能分组交换应用程序,否则它不太可能成为性能瓶颈。避免过早优化 - 设计程序的可测试性和可伸缩性,如果遇到性能问题,可以使用分析器查看瓶颈所在。
编辑:为了澄清,IPv4地址存储为32位整数,加上网络掩码(IP地址比较不需要)。如果您使用的是较新的且当前更为罕见的IPv6,则地址将为128位长。
答案 1 :(得分:7)
32位整数是要走的路 - 直到你开始处理128位IPv6地址。
答案 2 :(得分:5)
你的意思是你应该将它作为文本字符串进行比较,还是将int转换为int并比较为int?
这通常不是这种查找的瓶颈。你可以尝试实现这两种方法,看看哪一种运行得更快。
IP地址查找的真正问题通常是进行有效的查询,利用您处理IP地址而不仅仅是随机数的事实。要完成此任务,您可以查找LC trie和this article
显然,只有当您的黑名单中包含数万或数百万条目时,您才会感兴趣。如果它只有10-20个条目,则应首选线性搜索,实际上更有趣的问题是文本比较与整数比较。
答案 3 :(得分:5)
static public bool IsEqual(string ToCompare,
string CompareAgainst)
{
return IPAddressToLongBackwards(ToCompare)==IPAddressToLongBackwards(CompareAgainst);
}
static private uint IPAddressToLongBackwards(string IPAddr)
{
System.Net.IPAddress oIP=System.Net.IPAddress.Parse(IPAddr);
byte[] byteIP=oIP.GetAddressBytes();
uint ip=(uint)byteIP[0]<<24;
ip+=(uint)byteIP[1]<<16;
ip+=(uint)byteIP[2]<<8;
ip+=(uint)byteIP[3];
return ip;
}
如果我理解正确,这是比较两个IP地址的代码。你想要这个吗?你可以进一步做这样的事情:
static public bool IsGreater(string ToCompare,
string CompareAgainst)
{
return IPAddressToLongBackwards(ToCompare)>
IPAddressToLongBackwards(CompareAgainst);
}
因为你得到了地址字节。
答案 4 :(得分:4)
是的,我发现效率很高,但它会很长,当然你必须以整数形式索引列入黑名单的IP。
答案 5 :(得分:3)
使用像PeerGuardian这样的工具,它允许驱动程序级别的传入TCP / IP连接到黑名单上的IP。高度安全,无需代码(可以说:高度安全,因为无需代码)。
答案 6 :(得分:3)
我已经完成了这个并且我已经测试了它,使用unsigned int(32位)是最快的 - 我假设你将它与字符串表示进行比较。
可能对你有帮助的另一件事是在创建表时,过去我有2个列:LowIP和HighIP;通过这种方式,我能够通过1个记录条目将整个IP范围列入黑名单,并通过检查范围内的IP来获得良好的性能。
答案 7 :(得分:3)
我曾经继承了代码,其中某人想到将IP地址存储为4个int是一件非常好的事情,除非他们把所有时间都花在转换为int的上面。
将它们保存为数据库中的字符串要容易得多,而且只需要一个索引。你会惊讶于sql server能够索引字符串而不是4列整数。但是这个IP列表不是用于黑名单。数据库往返是非常昂贵的。
如果数据库过度,则将它们存储在内存中的字典中,但这只是猜测,因为我们不知道您需要比较多少。由于大多数哈希码都是32位int,而IPv4地址是32位,因此IP地址本身可能只是一个很好的哈希码。
但正如其他人所指出的,最好的选择可能是减少服务器上的负载并购买专用硬件。也许你最近将黑名单的IP保留在内存中,并定期向路由器发布新的IP。
如果你是那个试图在路由器中制作软件的人,那么你需要掏出你的数据结构书并创建类似b树的东西。
答案 8 :(得分:3)
答案 9 :(得分:2)
您是否存在效率问题?
如果是这样,那么一定要发布代码(或伪代码),我们可以选择尸体。
如果没有,那么我建议尝试一些简单的方法,例如将条目存储在排序列表中,并使用您现有的Sort()
和Find()
环境。
答案 10 :(得分:2)
整数比较比字符串比较快得多。
如果将整数存储在已排序的列表中,则可以比未排序的列表更快地找到它们。
答案 11 :(得分:1)
如果您将IP地址作为字符串接收,将其与字符串进行比较可能比将其转换为整数表示更有效
但是,如果几毫秒(纳秒!)对此操作有影响,我会对这两种解决方案进行分析; - )
答案 12 :(得分:1)
以下是我在JavaScript中使用过的
function isValidIPv4Range(iPv4Range = '') {
if (IP_V4_RANGE_REGEX.test(iPv4Range)) {
const [fromIp, toIp] = iPv4Range.split('-');
if (!isValidOctets(fromIp) || !isValidOctets(toIp)) {
return false;
}
const convertToNumericWeight = ip => {
const [octet1, octet2, octet3, octet4] = ip.split('.').map(parseInt);
return octet4 + (octet3 * 256) + (octet2 * 256 * 256) + (octet1 * 256 * 256 * 256);
};
return convertToNumericWeight(fromIp) < convertToNumericWeight(toIp);
}
return false;
}