public class IpHelper
    {
        // 核心方法:IP搜索
       /// <summary>
        /// 查找IP所属地区,确保web.config存在IPData或者BackIpData配置节
       /// </summary>
       /// <param name="ips">IP</param>
       /// <returns></returns>
        public static IpLocation GetIpLocation(string ips)
        {
            string fn =HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["IPData"]);
            string backData = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["BackIpData"]);
            if (!File.Exists(fn))
            {
                if (!File.Exists(backData))
                {
                    throw new Exception("文件不存在");
                }
                fn = backData;
            }
            FileStream fs = new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader fp = new BinaryReader(fs);
            //读文件头,获取首末记录偏移量
            int fo = fp.ReadInt32();
            int lo = fp.ReadInt32();
            //IP值
            uint ipv = IpStringToInt(ips);
            // 获取IP索引记录偏移值
            int rcOffset = getIndexOffset(fs, fp, fo, lo, ipv);
            fs.Seek(rcOffset, System.IO.SeekOrigin.Begin);

IpLocation ipl;
            if (rcOffset >= 0)
            {
                fs.Seek(rcOffset, System.IO.SeekOrigin.Begin);
                //读取开头IP值
                ipl.IpStart = fp.ReadUInt32();
                //转到记录体
                fs.Seek(ReadInt24(fp), System.IO.SeekOrigin.Begin);
                //读取结尾IP值
                ipl.IpEnd = fp.ReadUInt32();
                ipl.Country = GetString(fs, fp);
                ipl.City = GetString(fs, fp);
            }
            else
            {
                //没找到
                ipl.IpStart = 0;
                ipl.IpEnd = 0;
                ipl.Country = "未知国家";
                ipl.City = "未知地址";
            }
            fp.Close();
            fs.Close();
            return ipl;
        }

// 函数功能: 采用“二分法”搜索索引区, 定位IP索引记录位置
        private static int getIndexOffset(FileStream fs, BinaryReader fp, int _fo, int _lo, uint ipv)
        {
            int fo = _fo, lo = _lo;
            int mo;    //中间偏移量
            uint mv;    //中间值
            uint fv, lv; //边界值
            uint llv;   //边界末末值
            fs.Seek(fo, System.IO.SeekOrigin.Begin);
            fv = fp.ReadUInt32();
            fs.Seek(lo, System.IO.SeekOrigin.Begin);
            lv = fp.ReadUInt32();
            //临时作它用,末记录体偏移量
            mo = ReadInt24(fp);
            fs.Seek(mo, System.IO.SeekOrigin.Begin);
            llv = fp.ReadUInt32();
            //边界检测处理
            if (ipv < fv)
                return -1;
            else if (ipv > llv)
                return -1;
            //使用"二分法"确定记录偏移量
            do
            {
                mo = fo + (lo - fo) / 7 / 2 * 7;
                fs.Seek(mo, System.IO.SeekOrigin.Begin);
                mv = fp.ReadUInt32();
                if (ipv >= mv)
                    fo = mo;
                else
                    lo = mo;
                if (lo - fo == 7)
                    mo = lo = fo;
            } while (fo != lo);
            return mo;
        }

// 字符串数值型判断
        public static bool IsNumeric(string s)
        {
            if (s != null && System.Text.RegularExpressions.Regex.IsMatch(s, @"^-?\d+$"))
                return true;
            else
                return false;
        }
        // IP字符串->长整型值
        public static uint IpStringToInt(string IpString)
        {
            uint Ipv = 0;
            string[] IpStringArray = IpString.Split('.');
            int i;
            uint Ipi;
            for (i = 0; i < 4 && i < IpStringArray.Length; i++)
            {
                if (IsNumeric(IpStringArray[i]))
                {
                    Ipi = (uint)Math.Abs(Convert.ToInt32(IpStringArray[i]));
                    if (Ipi > 255) Ipi = 255;
                    Ipv += Ipi << (3 - i) * 8;
                }
            }
            return Ipv;
        }
        // 长整型值->IP字符串
        public static string IntToIpString(uint Ipv)
        {
            string IpString = "";
            IpString += (Ipv >> 24) + "." + ((Ipv & 0x00FF0000) >> 16) + "." + ((Ipv & 0x0000FF00) >> 8) + "." + (Ipv & 0x000000FF);
            return IpString;
        }
        // 读取字符串
        private static string ReadString(BinaryReader fp)
        {
            byte[] TempByteArray = new byte[128];
            int i = 0;
            do
            {
                TempByteArray[i] = fp.ReadByte();
            } while (TempByteArray[i++] != '\0' && i < 128);
            return System.Text.Encoding.Default.GetString(TempByteArray).TrimEnd('\0');
        }
        // 读取三字节的整数
        private static int ReadInt24(BinaryReader fp)
        {
            if (fp == null) return -1;
            int ret = 0;
            ret |= (int)fp.ReadByte();
            ret |= (int)fp.ReadByte() << 8 & 0xFF00;
            ret |= (int)fp.ReadByte() << 16 & 0xFF0000;
            return ret;
        }
        // 读取IP所在地字符串
        private static string GetString(FileStream fs, BinaryReader fp)
        {
            byte Tag;
            int Offset;
            Tag = fp.ReadByte();
            if (Tag == 0x01)  // 重定向模式1: 城市信息随国家信息定向
            {
                Offset = ReadInt24(fp);
                fs.Seek(Offset, System.IO.SeekOrigin.Begin);
                return GetString(fs, fp);
            }
            else if (Tag == 0x02) // 重定向模式2: 城市信息没有随国家信息定向
            {
                Offset = ReadInt24(fp);
                int TmpOffset = (int)fs.Position;
                fs.Seek(Offset, System.IO.SeekOrigin.Begin);
                string TmpString = GetString(fs, fp);
                fs.Seek(TmpOffset, System.IO.SeekOrigin.Begin);
                return TmpString;
            }
            else // 无重定向: 最简单模式
            {
                fs.Seek(-1, System.IO.SeekOrigin.Current);
                return ReadString(fp);
            }
        }
    }

// IP查询结果结构
   public struct IpLocation
   {
       public uint IpStart;
       public uint IpEnd;
       /// <summary>
       /// 国家或城市
       /// </summary>
       public string Country;
       /// <summary>
       /// 城市或详细地址
       /// </summary>
       public string City;
   }

IpHelper根据客户端IP进行网站分流的更多相关文章

  1. C#服务器获取客户端IP地址以及归属地探秘

    背景:博主本是一位Windows桌面应用程序开发工程师,对网络通信一知半解.一日老婆逛完某宝,问:"为什么他们知道我的地址呢,他们是怎么获取我的地址的呢?" 顺着这个问题我们的探秘 ...

  2. 用javascript得到客户端IP的新方法

    javascript得到客户端IP的新方法 很久以来,我都是经过http://fw.qq.com/ipaddress来得到客户端用户的IP,这个方法简单.快速.实用 . 我们调用它的写法是: < ...

  3. .net通过获取客户端IP地址反查出用户的计算机名

    这个功能看似很少用到,但又非常实用,看似简单,但又在其中存在很多未知因素造成让人悲痛莫名的负能量... 这是公司内部最近在使用的功能,因为是DHCP,所以有时会根据计算机名做一些统计和权限的设置. 也 ...

  4. 学习笔记_过滤器应用_1(分ip统计网站的访问次数)

    分ip统计网站的访问次数 ip count 192.168.1.111 2 192.168.1.112 59 统计工作需要在所有资源之前都执行,那么就可以放到Filter中了. 我们这个过滤器不打算做 ...

  5. Java web 实现 之 Filter分析ip统计网站的访问次数

    统计工作需要在所有资源之前都执行,那么就可以放到Filter中了. 我们这个过滤器不打算做拦截操作!因为我们只是用来做统计的. 用什么东西来装载统计的数据.Map<String,Integer& ...

  6. JS获取客户端IP地址、MAC和主机名七种方法

    一.使用JS获取客户端IP的几个方法方法一(只针对IE且客户端的IE允许AcitiveX运行,通过平台:XP,SERVER03,2000).获取客户端IP代码:<HTML><HEAD ...

  7. C# WebApi 获取客户端ip地址

    转自:http://www.cnblogs.com/weixing/p/5674078.html References required: HttpContextWrapper - System.We ...

  8. JS获取客户端IP地址、MAC和主机名的7个方法汇总

    今天在搞JS(javascript)获取客户端IP的小程序,上网搜了下,好多在现在的系统和浏览器中的都无效,很无奈,在Chrome.FireFox中很少搞到直接利用ActiveX获取IP等的JS脚本. ...

  9. WebService(JAX-WS、XFire、Axis三种)获取客户端ip

    WebService(JAX-WS.XFire.Axis三种)获取客户端ip JAX-WS.XFire.Axis三种webservice的获取客户端IP的简单实现过程: 1,基于JDK6 jax-ws ...

随机推荐

  1. 入门VMware Workstation下的Debian学习之Vim简单使用(三)

    什么是Vim? Vim具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计. Vim是从vi发展出来的一个文本编辑器.代码补完.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广 ...

  2. WPF DataGrid 样式设置

    隔行换色,鼠标单击,悬浮样式都有,其具体效果如图 1 所示. 图 1 WPF DataGrid 样式设置效果图 其中: 界面设计代码下所示 ? + 查看代码 1 2 3 4 5 6 7 8 9 10 ...

  3. 微服务架构中API网关的角色

    [上海尚学堂的话]:本文主要讲述了Mashape的首席技术执行官Palladino对API网关的详细介绍,以及API网关在微服务中所起的作用,同时介绍了Mashape的一款开源API网关Kong. A ...

  4. Android onSaveInstanceState和onRestoreInstanceState()

    首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Android开发过程中很少用到,但在有时候掌握其用法会帮我 ...

  5. jquery访问浏览器本地存储cookie,localStorage和sessionStorage

    前言:cookie,localStorage和sessionStorage都是浏览器本地存储数据的地方,其用法不尽相同:总结一下基本的用法. 一.cookie 定义: 存储在本地,容量最大4k,在同源 ...

  6. php中常用的字符串格式化函数

    ltrim():从字符串左删除空格或其他预定义字符串 rtrim():从字符串的末端开始删除空白字符串或其它预定义字符 trim():从字符串的两端删除空白字符和其他预定字符 str_pad():把字 ...

  7. sys.argv向脚本中传递参数

    可以向脚本中传递无限多个参数,其值是一个列表,默认sys.argv[0]内容是脚本文件路径加文件名 test.py文件中的内容如下: #! /usr/bin/python3import sys pri ...

  8. 学习SVG 重点汇总

    什么是SVG? Δ  SVG 指可伸缩矢量图形 (Scalable Vector Graphics) Δ  SVG 用来定义用于网络的基于矢量的图形 Δ  SVG使用XML格式来定义图形 Δ  SVG ...

  9. Hadoop(十四)MapReduce原理分析

    前言 上一篇我们分析了一个MapReduce在执行中的一些细节问题,这一篇分享的是MapReduce并行处理的基本过程和原理. Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于had ...

  10. LeetCode 252. Meeting Rooms (会议室)$

    Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...