<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    放翁(文初)的一畝三分地

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      210 隨筆 :: 1 文章 :: 320 評論 :: 0 Trackbacks
        下面是一段簡單的判斷一個ip是否在一組ip中的函數,其中ip和ip組的表達方式可以為這樣(ip="192.3.22.34",iplist="123.21.23.11,121.2.11.234,12.*.23.*"),下面紅色部分是開始一個同學寫的,藍色部分是后來我嘗試修改的。要說明的就以下幾點:
         1.很多時候優化可以在海量運算之前做好準備,例如分析的數據先做預處理,因為往往可讀性和計算效率會有沖突。
         2.如果沒有緩存,那么構建利于高效計算的代價可能超出簡單但計算效率一般的情況。
         3.在數據量很大的情況下,如何節省存儲直接決定你是否能夠緩存這些數據用于下次計算。

        有興趣的同學可以執行以下下面一些代碼(拷貝到eclipse格式化看和執行比較好):
        改動的主要內容在于對數據作預處理時增加了一點轉換,6位byte作為支持ipv6的存儲,第7位作為標識位來便于避免不需要的比對。
        用到了org.apache.commons.lang.StringUtils,它的split方法就是采用簡單的substring而不是pattern,效率很高,特別對于海量計算。

       具體的測試代碼:
       public static void  main(String[] args)
     {
      long beg = System.currentTimeMillis();
      
      //下面這些代碼是用于存粹比較計算時,對白名單做預編譯和緩存
      byte[][] whiteIps = prepare("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*");
      
      String[] allowIps = StringUtils.split("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*",",");
      List<String[]> whiteIps2 = new ArrayList<String[]>();
      if (null != allowIps && allowIps.length > 0) {
       for (int i = 0; i < allowIps.length; i++) {
        //把每個ip按“.”拆開,得到一個四位的數組
        String[] ipParse = StringUtils.split(allowIps[i], ".");
        whiteIps2.add(ipParse);
       }
      }
      
      for(int i = 0 ; i < 1000000 ; i++)
      {
       //第一組對比,增加了多一點的預處理,性能下降
       //checkAppIpWhite("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.19");
       //checkAppIpWhite("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.11");
       //checkAppIpWhiteV2("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.19");
       //checkAppIpWhiteV2("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.11");
       
       //存粹的比較計算,性能上升
    //   checkAppIpWhite(whiteIps2,"12.24.23.19");
    //   checkAppIpWhite(whiteIps2,"12.24.23.11");  
       checkAppIpWhiteV2(whiteIps,"12.24.23.19");
       checkAppIpWhiteV2(whiteIps,"12.24.23.11");
      }
      
      System.out.println("end test : " +  (System.currentTimeMillis() - beg));
     }


    老的比較代碼函數如下:
    public static boolean checkAppIpWhite(String ipWhilte,String remoteIp){
      if(StringUtils.isEmpty(ipWhilte) || StringUtils.isEmpty(remoteIp)){
       return true;
      }
      String[] allowIps = StringUtils.split(ipWhilte,",");
      List<String[]> whiteIps = new ArrayList<String[]>();
      if (null != allowIps && allowIps.length > 0) {
       for (int i = 0; i < allowIps.length; i++) {
        //把每個ip按“.”拆開,得到一個四位的數組
        String[] ipParse = StringUtils.split(allowIps[i], ".");
        whiteIps.add(ipParse);
       }
      }
      String[] requestParse = StringUtils.split(remoteIp, ".");
      for (String[] whiteIp : whiteIps) {
       if (ipsEqual(requestParse, whiteIp)) {
        return true;
       }
      }
      return false;
     }
     
     public static boolean checkAppIpWhite(List<String[]> whiteIps,String remoteIp){
      String[] requestParse = StringUtils.split(remoteIp, ".");
      for (String[] whiteIp : whiteIps) {
       if (ipsEqual(requestParse, whiteIp)) {
        return true;
       }
      }
      return false;
     }
     
     //判斷兩個ip是否相等
     public static boolean ipsEqual(String[] requestIp, String[] whiteIp) {
      boolean equal = false;
      
      //判斷白名單ip是否在列表中必須要兩個ip都不為空進行比較
      if (requestIp != null && whiteIp != null && requestIp.length == whiteIp.length) {   
       if (requestIp[0].equals(whiteIp[0])
         && requestIp[1].equals(whiteIp[1])
         && ("*".equals(whiteIp[2]) || requestIp[2]
           .equals(whiteIp[2]))
         && ("*".equals(whiteIp[3]) || requestIp[3]
           .equals(whiteIp[3]))) {
        equal = true;
       }
      }
      
      return equal;
     }

        

    新的代碼:
    public static boolean checkAppIpWhiteV2(String ipWhite,String remoteIp){
      
      if(StringUtils.isEmpty(ipWhite) || StringUtils.isEmpty(remoteIp)){
       return true;
      }
      
      byte[][] whiteIps = prepare(ipWhite);
      
      byte[] rIp = convertIp2Bytes(remoteIp);
      
      return isInclude(whiteIps,rIp);
      
     }
     
     public static boolean checkAppIpWhiteV2(byte[][] whiteIps,String remoteIp)
     {
      byte[] rIp = convertIp2Bytes(remoteIp);
      
      return isInclude(whiteIps,rIp);
     }
     
     public static  boolean isInclude(byte[][] whiteIps,byte[] rIp)
     {
      boolean result = false;
      
      for(byte[] whiteIp : whiteIps)
      {
       for(int i = 1; i < 7; i++)
       {
        byte n = (byte)(1 << (i-1));
        
        if ((whiteIp[0] & n) != n)
        {
         if (i == 6)
          return true;
         else
          continue;
        }
        else
        {
         if (whiteIp[i] != rIp[i-1])
          break;
        }
        
        
        if (i == 6)
        {
         return true;
        }
       }
      }
      
      return result;
     }
     
     public static byte[] convertIp2Bytes(String remoteIp)
     {
      byte[] result = new byte[6];
      
      String[] points = StringUtils.split(remoteIp,".");
      
      int cursor = 0;
      
      for(String point : points)
      {
       int i = Integer.parseInt(point);
       
       if (i > Byte.MAX_VALUE)
        result[cursor] = (byte)(i - Byte.MAX_VALUE);
       else
        result[cursor] = (byte)i; 
       
       cursor += 1;
      }
      
      return result;
     }
     
     public static byte[][] prepare(String ipWhite)
     {
      String[] allowIps = StringUtils.split(ipWhite,",");//性能很好
      byte[][] result = new byte[allowIps.length][7];
      
      int cursorX = 0;
      
      for(String allowIp : allowIps)
      {
       String[] points = StringUtils.split(allowIp,".");
       
       int cursorY = 0;
       byte checkbits = 0;
       
       for(String point : points)
       {
        if (!point.equals("*"))
        {
         checkbits += 1 << cursorY;
         
         int i = Integer.parseInt(point);
         
         if (i > Byte.MAX_VALUE)
          result[cursorX][cursorY + 1] = (byte)(i - Byte.MAX_VALUE);
         else
          result[cursorX][cursorY + 1] = (byte)i; 
        }
        cursorY += 1;
       }
       
       result[cursorX][0] = checkbits;
       cursorX += 1;
      }
      
      return result;
      
     }
       
    posted on 2011-04-13 23:11 岑文初 閱讀(4587) 評論(1)  編輯  收藏

    評論

    # re: 一段代碼,幾句話 2011-04-28 10:46 北京王錚
    這個還可以再進一步優化下吧  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲人成www在线播放| 亚洲AV色香蕉一区二区| 一本色道久久88亚洲精品综合| 久久一区二区三区免费播放| 亚洲精品国产精品乱码在线观看 | 国产偷国产偷亚洲高清人| 最近中文字幕无吗免费高清 | 永久免费bbbbbb视频| 亚洲成a∧人片在线观看无码| 精品国产免费一区二区| 亚洲精品无码aⅴ中文字幕蜜桃| 久久久久久国产精品免费免费| 亚洲狠狠成人综合网| 日韩免费观看的一级毛片| 国产亚洲福利一区二区免费看| 国产一级淫片视频免费看| 黄色毛片免费在线观看| 久久久久亚洲精品男人的天堂| 大地资源中文在线观看免费版| 亚洲Av综合色区无码专区桃色| 老汉精品免费AV在线播放| 亚洲一区精品视频在线| 国产一区二区三区在线免费| 久久久受www免费人成| 亚洲色图.com| 成年男女男精品免费视频网站 | 91在线亚洲精品专区| 青青青免费国产在线视频小草| 亚洲日韩精品国产3区| 亚洲国产精品狼友中文久久久 | 黄色片在线免费观看| 国产精品久久久久久亚洲影视| 国产亚洲成人久久| 久久精品毛片免费观看| 亚洲欧洲免费无码| 亚洲午夜无码久久久久| 日本免费网址大全在线观看| 窝窝影视午夜看片免费| 亚洲冬月枫中文字幕在线看| 国产zzjjzzjj视频全免费 | 亚洲乱人伦精品图片|