c#实现根据网络IP显示地理位置功能

时间:2021-09-03 10:56:15

用户信息表,是大多数系统都有的。我们也知道,通常都会有类似 注册IP 和 最后登录IP 这两个的字段,来存储用户注册时候的IP地址和最后登录的IP的地址。

获取这样的地址,在后台显示 xxx.xxx.xxx.xxx 的地址段,让人看到很不自然,根本就不知道具体地理位置。

现在我们就简单的实现一下这个功能。

用到了 读取纯真IP数据库的公用组件QQWry.NET 这个组件,作者阿不。(谢谢他的共享)

还要去下载最新的纯真IP地址库,下载获得QQWry.dat

最后请出Js中的小靓妞,jquery-1.3.1.js

新建Web项目AjaxIP,将QQWry.dat添加到App_Data下。

然后添加QQWry.NET的组件类,如下:

c#实现根据网络IP显示地理位置功能c#实现根据网络IP显示地理位置功能  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.IO;
  5 using System.Text.RegularExpressions;
  6 using System.Net;
  7 using System.Net.Sockets;
  8 
  9 namespace AjaxIP
 10 {
 11     public class IPLocation
 12     {
 13         public string IP { getset; }
 14         public string Country { getset; }
 15         public string Local { getset; }
 16     }
 17 
 18     public class QQWryLocator
 19     {
 20         static Encoding encoding = Encoding.GetEncoding("GB2312");
 21 
 22         private byte[] data;
 23         int firstStartIpOffset;
 24         int lastStartIpOffset;
 25         int ipCount;
 26 
 27         public int Count { get { return ipCount; } }
 28 
 29         public QQWryLocator(string dataPath)
 30         {
 31             using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
 32             {
 33                 data = new byte[fs.Length];
 34                 fs.Read(data, 0, data.Length);
 35             }
 36 
 37             firstStartIpOffset = (int)data[0+ (((int)data[1]) << 8+ (((int)data[2]) << 16+ (((int)data[3]) << 24);
 38             lastStartIpOffset = (int)data[4+ (((int)data[5]) << 8+ (((int)data[6]) << 16+ (((int)data[7]) << 24);
 39             ipCount = (lastStartIpOffset - firstStartIpOffset) / 7 + 1;
 40 
 41             if (ipCount <= 1)
 42             {
 43                 throw new ArgumentException("ip FileDataError");
 44             }
 45         }
 46 
 47         public static uint IpToInt(string ip)
 48         {
 49             //string[] strArray = ip.Split('.');
 50             //return (uint.Parse(strArray[0]) << 24) + (uint.Parse(strArray[1]) << 16) + (uint.Parse(strArray[2]) << 8) + uint.Parse(strArray[0]);
 51             //return (uint)IPAddress.HostToNetworkOrder((int)(IPAddress.Parse(ip).Address));
 52 
 53             byte[] bytes = IPAddress.Parse(ip).GetAddressBytes();
 54             return (uint)bytes[3+ (((uint)bytes[2]) << 8+ (((uint)bytes[1]) << 16+ (((uint)bytes[0]) << 24);
 55         }
 56 
 57         public static string IntToIP(uint ip_Int)
 58         {
 59             return new IPAddress(ip_Int).ToString();
 60         }
 61 
 62         public IPLocation Query(string ip)
 63         {
 64             IPAddress address = IPAddress.Parse(ip);
 65             if (address.AddressFamily != AddressFamily.InterNetwork)
 66             {
 67                 throw new ArgumentException("不支持非IPV4的地址");
 68             }
 69 
 70             if (IPAddress.IsLoopback(address))
 71             {
 72                 return new IPLocation() { IP = ip, Country = "本机内部环回地址", Local = string.Empty };
 73             }
 74 
 75             uint intIP = (uint)IPAddress.HostToNetworkOrder((int)address.Address);
 76 
 77             //if ((((intIP >= IpToInt("0.0.0.0")) && (intIP <= IpToInt("2.255.255.255"))) || ((intIP >= IpToInt("64.0.0.0")) && (intIP <= IpToInt("126.255.255.255")))) ||
 78             //((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))
 79             //if (intIP <= 50331647 || (intIP >= 1073741824 && intIP <= 2130706431) || (intIP >= 973078528 && intIP <= 1023410175))
 80             //{
 81             //    return new IPLocation() { IP = ip, Country = "网络保留地址", Local = string.Empty };
 82             //}
 83 
 84             IPLocation ipLocation = new IPLocation() { IP = ip };
 85 
 86             uint right = (uint)ipCount;
 87             uint left = 0;
 88             uint middle = 0;
 89             uint startIp = 0;
 90             uint endIpOff = 0;
 91             uint endIp = 0;
 92             int countryFlag = 0;
 93 
 94             while (left < (right - 1))
 95             {
 96                 middle = (right + left) / 2;
 97                 startIp = GetStartIp(middle, out endIpOff);
 98                 if (intIP == startIp)
 99                 {
100                     left = middle;
101                     break;
102                 }
103                 if (intIP > startIp)
104                 {
105                     left = middle;
106                 }
107                 else
108                 {
109                     right = middle;
110                 }
111             }
112             startIp = GetStartIp(left, out endIpOff);
113             endIp = GetEndIp(endIpOff, out countryFlag);
114             if ((startIp <= intIP) && (endIp >= intIP))
115             {
116                 string local;
117                 ipLocation.Country = GetCountry(endIpOff, countryFlag, out local);
118                 ipLocation.Local = local;
119             }
120             else
121             {
122                 ipLocation.Country = "未知";
123                 ipLocation.Local = string.Empty;
124             }
125             return ipLocation;
126         }
127 
128         private uint GetStartIp(uint left, out uint endIpOff)
129         {
130             int leftOffset = (int)(firstStartIpOffset + (left * 7));
131             endIpOff = (uint)data[4 + leftOffset] + (((uint)data[5 + leftOffset]) << 8+ (((uint)data[6 + leftOffset]) << 16);
132             return (uint)data[leftOffset] + (((uint)data[1 + leftOffset]) << 8+ (((uint)data[2 + leftOffset]) << 16+ (((uint)data[3 + leftOffset]) << 24);
133         }
134 
135         private uint GetEndIp(uint endIpOff, out int countryFlag)
136         {
137             countryFlag = data[4 + endIpOff];
138             return (uint)data[endIpOff] + (((uint)data[1 + endIpOff]) << 8+ (((uint)data[2 + endIpOff]) << 16+ (((uint)data[3 + endIpOff]) << 24);
139         }
140 
141         /// <summary>
142         /// Gets the country.
143         /// </summary>
144         /// <param name="endIpOff">The end ip off.</param>
145         /// <param name="countryFlag">The country flag.</param>
146         /// <param name="local">The local.</param>
147         /// <returns>country</returns>
148         private string GetCountry(uint endIpOff, int countryFlag, out string local)
149         {
150             string country = string.Empty;
151             uint offset = endIpOff + 4;
152             switch (countryFlag)
153             {
154                 case 1:
155                 case 2:
156                     country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
157                     offset = endIpOff + 8;
158                     local = (1 == countryFlag) ? string.Empty : GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
159                     break;
160                 default:
161                     country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
162                     local = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
163                     break;
164             }
165             return country;
166         }
167 
168         private string GetFlagStr(ref uint offset, ref int countryFlag, ref uint endIpOff)
169         {
170             int flag = 0;
171             while (true)
172             {
173                 flag = data[offset];
174                 //没有重定向
175                 if (flag != 1 && flag != 2)
176                 {
177                     break;
178                 }
179                 if (flag == 2)
180                 {
181                     countryFlag = 2;
182                     endIpOff = offset - 4;
183                 }
184                 offset = (uint)data[1 + offset] + (((uint)data[2 + offset]) << 8+ (((uint)data[3 + offset]) << 16);
185             }
186             if (offset < 12)
187             {
188                 return string.Empty;
189             }
190             return GetStr(ref offset);
191         }
192 
193         /// <summary>
194         /// 读取字符串...
195         /// </summary>
196         /// <param name="offset"></param>
197         /// <returns></returns>
198         private string GetStr(ref uint offset)
199         {
200             byte lowByte = 0;
201             byte highByte = 0;
202             StringBuilder stringBuilder = new StringBuilder(16);
203             while (true)
204             {
205                 lowByte = data[offset++];
206                 if (lowByte == 0)
207                 {
208                     return stringBuilder.ToString();
209                 }
210 
211                 if (lowByte > 0x7f)
212                 {
213                     highByte = data[offset++];
214                     if (highByte == 0)
215                     {
216                         return stringBuilder.ToString();
217                     }
218                     stringBuilder.Append(encoding.GetString(new byte[] { lowByte, highByte }));
219                 }
220                 else
221                 {
222                     stringBuilder.Append((char)lowByte);
223                 }
224             }
225         }
226     }
227 }
c#实现根据网络IP显示地理位置功能

 再来新建 IPSearch.ashx 文件,如下:

c#实现根据网络IP显示地理位置功能c#实现根据网络IP显示地理位置功能 1 using System;
 2 using System.Collections;
 3 using System.Data;
 4 using System.Linq;
 5 using System.Web;
 6 using System.Web.Services;
 7 using System.Web.Services.Protocols;
 8 using System.Xml.Linq;
 9 
10 namespace AjaxIP
11 {
12     /// <summary>
13     /// IP查询 的摘要说明
14     /// </summary>
15     public class IPSearch : IHttpHandler
16     {
17 
18         public void ProcessRequest(HttpContext context)
19         {
20             context.Response.ContentType = "text/plain";
21             string ip = context.Request["ip"];
22             string ipFilePath = @"\App_Data\QQWry.dat";
23             QQWryLocator QQWry = new QQWryLocator(ipFilePath);
24             IPLocation loc = QQWry.Query(ip);
25 
26             context.Response.Write(string.Format("{0} {1}",loc.Country,loc.Local));
27         }
28 
29         public bool IsReusable
30         {
31             get
32             {
33                 return false;
34             }
35         }
36     }
37 }
c#实现根据网络IP显示地理位置功能

最后在Default.aspx页面写下,js和有IP的用户信息,如下:

c#实现根据网络IP显示地理位置功能c#实现根据网络IP显示地理位置功能 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 
 3 <html xmlns="http://www.w3.org/1999/xhtml" >
 4 <head runat="server">
 5     <title></title>
 6 <script language="javascript" src="Js/jquery-1.3.1.js"></script>
 7 <script language="javascript">
 8     $(document).ready(function() {
 9         $("#tb tr").each(function() {
10             var obj = $(this).children("td:eq(2)");
11             SearchIP(obj);
12         });
13     })
14 
15     function SearchIP(obj) {
16     $.ajax({
17         type: "GET",
18         url: "IPSearch.ashx?ip=" + obj.text(),
19         success: function(data) {
20             obj.text(data);
21         }
22     });
23 }
24 </script>
25 </head>
26 <body>
27     <form id="form1" runat="server">
28     <div>
29     
30         <table id="tb" style="width:100%;">
31             <thead>
32                 <th>321321</th>
33                 <th>321321</th>
34                 <th>321321</th>
35             </thead> 
36             <tr>
37                 <td>
38                     OMEGA</td>
39                 <td>
40                     0</td>
41                 <td>
42                     122.229.191.8</td>
43             </tr>
44             <tr>
45                 <td>
46                     荒年</td>
47                 <td>
48                     900,000</td>
49                 <td>
50                     110.87.98.30</td>
51             </tr>
52             <tr>
53                 <td>
54                     寒妃</td>
55                 <td>
56                     1,854,257,979</td>
57                 <td>
58                     220.188.193.72</td>
59             </tr>
60             <tr>
61                 <td>
62                     哈小土</td>
63                 <td>
64                     600,100</td>
65                 <td>
66                     220.188.193.72</td>
67             </tr>
68             <tr>
69                 <td>
70                     化妆造型</td>
71                 <td>
72                     400,100</td>
73                 <td>
74                     220.188.193.72</td>
75             </tr>
76         </table>
77     
78     </div>
79     </form>
80 </body>
81 </html>
c#实现根据网络IP显示地理位置功能

这样我们的后台用户信息不再是不友好的IP地址段了。

运行一下,看看效果吧。