IP地址地理定位

3
我希望通过大陆来定位我的服务器请求。
基本上,在做了一些初步研究之后,似乎有三种方法:1)使用浏览器提供的地理位置(但我认为没有人真正点击“是”当浏览器要求使用地理位置时);2)获取IP地址列表,将该列表放在您服务器上的数据库中,然后每次请求进来时,从此数据库中读取;我不想在每个请求中都访问数据库。3)向外部服务器发出HTTP调用以获取位置;甚至可能比第二种方法更慢。
基本上,我并不关心用户确切的位置,我只需要知道他们所在的大陆:北美洲,欧洲...
有没有一种方法可以做到这一点,既不需要任何用户交互,也不需要在每个请求上读取数据库?当我进入www.intel.com时,我会被自动重定向到法国网站;他们是怎么做到的?
谢谢您的建议。

你可以尝试检查Accept-Language头,但你仍然需要一个备选方案,在这种情况下,我认为一些地理数据库仍然是你最好的猜测。 - sroes
3个回答

7

有一些免费和商业数据库可以根据IP地址告诉你它来自哪里。

免费的数据库来自maxmind [*]: http://dev.maxmind.com/geoip/geolite

还有两个商业数据库:
http://www.ip2location.com
http://www.maxmind.com

在这个网站上,你也可以找到asp.net的示例,了解如何使用这些数据。此外,他们还提供其他免费服务,可以查看用户来自哪里。

从这里获取API示例和数据库:http://www.maxmind.com/download/geoip/

如果只需要国家,则可以使用此数据库文件。

http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

这段文字只包含国家信息,并且与其余内容相比较小。

简单来说,数据库的格式如下:

"1.20.0.0","1.20.255.255","18087936","18153471","TH","Thailand"
"1.21.0.0","1.21.255.255","18153472","18219007","JP","Japan"
"1.22.0.0","1.23.255.255","18219008","18350079","IN","India"
"1.24.0.0","1.31.255.255","18350080","18874367","CN","China" 

长数字是 IP 的翻译。因此,您可以读取用户的 IP,然后使用函数将其转换为长数字,然后搜索数据库,找到与该长数字匹配的记录。
public long addrToNum(IPAddress Address)
{
    byte[] b = BitConverter.GetBytes(Address.Address);

    if (b.Length == 8)
        return (long)(((long)16777216 * b[0]) + ((long)(65536 * b[1])) + ((long)(256 * b[2])) + b[3]);
    else
        return 0;
}

如果您将它们添加到数据库中,则可以在这些长数字上对数据库进行索引,并查找 IP 所在的位置,如下所示:

Select TOP 1 * from GeoIPCountryWhois WITH (NOLOCK) Where @myIpToLong BETWEEN begin_num AND end_num

把结果缓存在会话变量中,而不是在每个页面请求中再次搜索,这样做很好。

[*] 非常感谢maxmind与商业数据库一起发布免费数据库。


我需要哪一个:GeoLite Country IPv6还是GeoLite Country? - frenchie
@frenchie GeoLite Country - 使用IPv6的是v6 IP地址 - 我不知道IP v6是否返回所有内容,但旧IP地址在所有情况下均可用。 - Aristos
在性能方面,扫描具有100万行的数据库是否会成为问题? - frenchie
@frenchie 如果您使用大型数据库,则需要将其添加到MS Sql或MySql中,然后在那里索引ips的起始/结束位置,这样搜索速度非常快,但最好将结果缓存到会话中,而不是在每次调用时扫描位置,只需在第一次调用时扫描即可。如果您使用国家数据库,则速度更快,因为它更小。在目录中有一个C#的国家示例,您可以非常容易地使用它。我使用它,并已添加到MS SQL中。 - Aristos
是的,我计划在Sql Server中完成它。谢谢你的回答;我想我会选择一个DB调用。 - frenchie

0

0

看起来你更喜欢第二种方式,但你不需要在每个请求中都访问数据库 - 只需将结果缓存到 cookie 中即可。

再说一点疯狂的想法 - 让你考虑额外的数据库请求成本:你可以将某些地理数据库(查找 Aristos 的答案)转换为你的需求。每个 IP 都可以转换为 Int64,并且您可以制作大陆范围,同时将数据库转换为您的格式。例如,0-10000 将是北美,10000-20000 将是欧洲,20000-30000 再次是北美,以此类推,而在这些范围内仅需查找 IP。

但是,你需要做大量的工作才能进行这样的转换,并且不要忘记它会是一个真正的大麻烦头痛问题:IP 基础并不是恒定的。
因此,数据库请求+缓存可能是最好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接