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

  用户信息表,是大多数系统都有的。我们也知道,通常都会有类似 注册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的组件类,如下:

  

复制代码 代码如下:

  Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 using System;

  using System.Collections.Generic;

  using System.Text;

  using System.IO;

  using System.Text.RegularExpressions;

  using System.Net;

  using System.Net.Sockets;

  namespace AjaxIP

  {

  public class IPLocation

  {

  public string IP { get; set; }

  public string Country { get; set; }

  public string Local { get; set; }

  }

  public class QQWryLocator

  {

  static Encoding encoding = Encoding.GetEncoding("GB2312");

  private byte[] data;

  int firstStartIpOffset;

  int lastStartIpOffset;

  int ipCount;

  public int Count { get { return ipCount; } }

  public QQWryLocator(string dataPath)

  {

  using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))

  {

  data = new byte[fs.Length];

  fs.Read(data, 0, data.Length);

  }

  firstStartIpOffset = (int)data[0] + (((int)data[1]) << 8) + (((int)data[2]) << 16) + (((int)data[3]) << 24);

  lastStartIpOffset = (int)data[4] + (((int)data[5]) << 8) + (((int)data[6]) << 16) + (((int)data[7]) << 24);

  ipCount = (lastStartIpOffset - firstStartIpOffset) / 7 + 1;

  if (ipCount <= 1)

  {

  throw new ArgumentException("ip FileDataError");

  }

  }

  public static uint IpToInt(string ip)

  {

  //string[] strArray = ip.Split('.');

  //return (uint.Parse(strArray[0]) << 24) + (uint.Parse(strArray[1]) << 16) + (uint.Parse(strArray[2]) << 8) + uint.Parse(strArray[0]);

  //return (uint)IPAddress.HostToNetworkOrder((int)(IPAddress.Parse(ip).Address));

  byte[] bytes = IPAddress.Parse(ip).GetAddressBytes();

  return (uint)bytes[3] + (((uint)bytes[2]) << 8) + (((uint)bytes[1]) << 16) + (((uint)bytes[0]) << 24);

  }

  public static string IntToIP(uint ip_Int)

  {

  return new IPAddress(ip_Int).ToString();

  }

  public IPLocation Query(string ip)

  {

  IPAddress address = IPAddress.Parse(ip);

  if (address.AddressFamily != AddressFamily.InterNetwork)

  {

  throw new ArgumentException("不支持非IPV4的地址");

  }

  if (IPAddress.IsLoopback(address))

  {

  return new IPLocation() { IP = ip, Country = "本机内部环回地址", Local = string.Empty };

  }

  uint intIP = (uint)IPAddress.HostToNetworkOrder((int)address.Address);

  //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")))) ||

  //((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))

  //if (intIP <= 50331647 || (intIP >= 1073741824 && intIP <= 2130706431) || (intIP >= 973078528 && intIP <= 1023410175))

  //{

  // return new IPLocation() { IP = ip, Country = "网络保留地址", Local = string.Empty };

  //}

  IPLocation ipLocation = new IPLocation() { IP = ip };

  uint right = (uint)ipCount;

  uint left = 0;

  uint middle = 0;

  uint startIp = 0;

  uint endIpOff = 0;

  uint endIp = 0;

  int countryFlag = 0;

  while (left < (right - 1))

  {

  middle = (right + left) / 2;

  startIp = GetStartIp(middle, out endIpOff);

  if (intIP == startIp)

  {

  left = middle;

  break;

  }

  if (intIP > startIp)

  {

  left = middle;

  }

  else

  {

  right = middle;

  }

  }

  startIp = GetStartIp(left, out endIpOff);

  endIp = GetEndIp(endIpOff, out countryFlag);

  if ((startIp <= intIP) && (endIp >= intIP))

  {

  string local;

  ipLocation.Country = GetCountry(endIpOff, countryFlag, out local);

  ipLocation.Local = local;

  }

  else

  {

  ipLocation.Country = "未知";

  ipLocation.Local = string.Empty;

  }

  return ipLocation;

  }

  private uint GetStartIp(uint left, out uint endIpOff)

  {

  int leftOffset = (int)(firstStartIpOffset + (left * 7));

  endIpOff = (uint)data[4 + leftOffset] + (((uint)data[5 + leftOffset]) << 8) + (((uint)data[6 + leftOffset]) << 16);

  return (uint)data[leftOffset] + (((uint)data[1 + leftOffset]) << 8) + (((uint)data[2 + leftOffset]) << 16) + (((uint)data[3 + leftOffset]) << 24);

  }

  private uint GetEndIp(uint endIpOff, out int countryFlag)

  {

  countryFlag = data[4 + endIpOff];

  return (uint)data[endIpOff] + (((uint)data[1 + endIpOff]) << 8) + (((uint)data[2 + endIpOff]) << 16) + (((uint)data[3 + endIpOff]) << 24);

  }

  /// <summary>

  /// Gets the country.

  /// </summary>

  /// <param name="endIpOff">The end ip off.</param>

  /// <param name="countryFlag">The country flag.</param>

  /// <param name="local">The local.</param>

  /// <returns>country</returns>

  private string GetCountry(uint endIpOff, int countryFlag, out string local)

  {

  string country = string.Empty;

  uint offset = endIpOff + 4;

  switch (countryFlag)

  {

  case 1:

  case 2:

  country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);

  offset = endIpOff + 8;

  local = (1 == countryFlag) ? string.Empty : GetFlagStr(ref offset, ref countryFlag, ref endIpOff);

  break;

  default:

  country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);

  local = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);

  break;

  }

  return country;

  }

  private string GetFlagStr(ref uint offset, ref int countryFlag, ref uint endIpOff)

  {

  int flag = 0;

  while (true)

  {

  flag = data[offset];

  //没有重定向

  if (flag != 1 && flag != 2)

  {

  break;

  }

  if (flag == 2)

  {

  countryFlag = 2;

  endIpOff = offset - 4;

  }

  offset = (uint)data[1 + offset] + (((uint)data[2 + offset]) << 8) + (((uint)data[3 + offset]) << 16);

  }

  if (offset < 12)

  {

  return string.Empty;

  }

  return GetStr(ref offset);

  }

  /// <summary>

  /// 读取字符串...

  /// </summary>

  /// <param name="offset"></param>

  /// <returns></returns>

  private string GetStr(ref uint offset)

  {

  byte lowByte = 0;

  byte highByte = 0;

  StringBuilder stringBuilder = new StringBuilder(16);

  while (true)

  {

  lowByte = data[offset++];

  if (lowByte == 0)

  {

  return stringBuilder.ToString();

  }

  if (lowByte > 0x7f)

  {

  highByte = data[offset++];

  if (highByte == 0)

  {

  return stringBuilder.ToString();

  }

  stringBuilder.Append(encoding.GetString(new byte[] { lowByte, highByte }));

  }

  else

  {

  stringBuilder.Append((char)lowByte);

  }

  }

  }

  }

  }

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

  

复制代码 代码如下:

  Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 using System;

  using System.Collections;

  using System.Data;

  using System.Linq;

  using System.Web;

  using System.Web.Services;

  using System.Web.Services.Protocols;

  using System.Xml.Linq;

  namespace AjaxIP

  {

  /// <summary>

  /// IP查询 的摘要说明

  /// </summary>

  public class IPSearch : IHttpHandler

  {

  public void ProcessRequest(HttpContext context)

  {

  context.Response.ContentType = "text/plain";

  string ip = context.Request["ip"];

  string ipFilePath = @"\App_Data\QQWry.dat";

  QQWryLocator QQWry = new QQWryLocator(ipFilePath);

  IPLocation loc = QQWry.Query(ip);

  context.Response.Write(string.Format("{0} {1}",loc.Country,loc.Local));

  }

  public bool IsReusable

  {

  get

  {

  return false;

  }

  }

  }

  }

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

  

复制代码 代码如下:

  Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <html xmlns="http://www.w3.org/1999/xhtml" >

  <head runat="server">

  <title></title>

  <script language="javascript" src="Js/jquery-1.3.1.js"></script>

  <script language="javascript">

  $(document).ready(function() {

  $("#tb tr").each(function() {

  var obj = $(this).children("td:eq(2)");

  SearchIP(obj);

  });

  })

  function SearchIP(obj) {

  $.ajax({

  type: "GET",

  url: "IPSearch.ashx?ip=" + obj.text(),

  success: function(data) {

  obj.text(data);

  }

  });

  }

  </script>

  </head>

  <body>

  <form id="form1" runat="server">

  <div>

  <table id="tb" style="width:100%;">

  <thead>

  <th>321321</th>

  <th>321321</th>

  <th>321321</th>

  </thead>

  <tr>

  <td>

  OMEGA</td>

  <td>

  0</td>

  <td>

  122.229.191.8</td>

  </tr>

  <tr>

  <td>

  荒年</td>

  <td>

  900,000</td>

  <td>

  110.87.98.30</td>

  </tr>

  <tr>

  <td>

  寒妃</td>

  <td>

  1,854,257,979</td>

  <td>

  220.188.193.72</td>

  </tr>

  <tr>

  <td>

  哈小土</td>

  <td>

  600,100</td>

  <td>

  220.188.193.72</td>

  </tr>

  <tr>

  <td>

  化妆造型</td>

  <td>

  400,100</td>

  <td>

  220.188.193.72</td>

  </tr>

  </table>

  </div>

  </form>

  </body>

  </html>

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

  运行一下,看看效果吧.