<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 北京王錚
    這個還可以再進一步優化下吧  回復  更多評論
      


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


    網站導航:
     
    主站蜘蛛池模板: 亚洲国产精品成人AV在线| 97无码人妻福利免费公开在线视频 | 久久九九AV免费精品| 亚洲日本国产乱码va在线观看| 午夜网站免费版在线观看| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 中文字幕无码播放免费| 色噜噜的亚洲男人的天堂| 国外亚洲成AV人片在线观看| 国产2021精品视频免费播放| 曰批全过程免费视频观看免费软件| 亚洲Av综合色区无码专区桃色| 成年在线观看免费人视频草莓| 久久免费国产精品| 亚洲色大成网站WWW国产| 亚洲中文字幕无码一区| 浮力影院第一页小视频国产在线观看免费| 亚洲第一视频在线观看免费| 亚洲黄色激情视频| 亚洲中文字幕无码一区二区三区| 最近中文字幕免费mv视频8| 光棍天堂免费手机观看在线观看 | 久久夜色精品国产亚洲AV动态图| 毛片免费在线播放| 免费福利电影在线观看| 亚洲а∨精品天堂在线| 亚洲无圣光一区二区| 国产亚洲综合成人91精品| 国产精品嫩草影院免费| 亚洲天堂免费在线| 日本免费人成网ww555在线| 香蕉视频免费在线| 久久夜色精品国产噜噜亚洲a| 久久精品夜色国产亚洲av| 亚洲人成国产精品无码| 精品久久免费视频| 成年在线观看免费人视频草莓| 2020因为爱你带字幕免费观看全集| 国产99久久久久久免费看| 久久精品国产亚洲AV电影网| 亚洲国色天香视频|