MySQL协议分析

jopen 10年前

参考资料:

http://dev.mysql.com/doc/internals/en/client-server-protocol.html

http://www.haodaima.net/art/2574673

http://hutaow.com/blog/2013/11/06/mysql-protocol-analysis/#11

http://blog.csdn.net/gapaul/article/details/12046843



mysql起始握手,先由server发起,client分析并回应自已同意的特性,然后双方依照这些特性处理数据包。

通信时是否采用压缩会改变数据包的字节变化。

客户端的特性在首个回应(既握手包)服务器中体现,如:是否开启压缩、字符集、用户登录信息等。


1.未采用压缩时,客户端向服务器发送的包格式:

格式:3*byte,1*byte,1*byte,n*byte

表示:消息长度,包序号,请求类型,请求内容


2.采用压缩后,客户端向服务器发送的包格式:

格式:3*byte,1*byte,3*byte,3*byte,n*byte

表示:消息长度,包序号,压缩包大小,压缩包内容

当压缩包大小为0x00时,表示当前包未采用压缩,则n*byte内容为1*byte,n*byte,既请求类型,请求内容

当压缩包大小大于0x00时,表示当前包已采用zlib压缩,则n*byte内容,先解压缩,解压后内容为1*byte,n*byte,既请求类型,请求内容。


package mysql;    import java.io.UnsupportedEncodingException;  import java.util.HashMap;  import java.util.Map;    /**   * 支持mysql 4.1+,不支持ssl   * @author shanl   *   */  public class MysqlAnalyse {   /**传输包默认最大长度16M*/   public static final int PACKET_MAXIMUM_LENGTH = 1024*1024*16;       Map<String,Object> properties = new HashMap<String,Object>();  // StringBuilder sql = new StringBuilder();   long requestType = -1;   boolean endPacket = true;     // int packetLen = PACKET_MAXIMUM_LENGTH;    byte[] _packet = null;   int _off = 0;   int _len = 0;      /**    * 默认开启压缩、utf-8编码    */   public MysqlAnalyse(){    this.setProperty("compress", true);    this.setProperty("encoding", "utf-8");   }        /**    * <b>通过客户端向服务端回应的握手包,获得一个MysqlAnlayse实例。</b> <br/>    * 建立连接时,server先向client发送握手包,此包包括server支持的特性和编码等信息,<br/>    * client回应包中需要说明本地支持什么特性,比如是否支持(zlib)压缩。    * @param buff    * @param off    * @param len    * @return    * @see <a href="http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse">    * http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse<a/>     */   public static MysqlAnalyse handshake(byte[] buff,int off,int len){    MysqlAnalyse anly = new MysqlAnalyse();    //2 byte,capability_flags    long capability_flags = Util.bigBys2Uint32(new byte[]{      buff[off],buff[off+1]    }, 0, 2);        //4byte,前2byte表示mysql特性(如下:是否开启压缩),后2byte客户端扩展特性    boolean compress = CapabilityFlag.CLIENT_COMPRESS==(CapabilityFlag.CLIENT_COMPRESS & capability_flags);    anly.setProperty("compress", compress);          //4byte,最大发送包字节数    long max_packet_size = Util.bigBys2Uint32(new byte[]{      buff[off+4],buff[off+5],      buff[off+6],buff[off+7]    }, 0, 4);    anly.setProperty("max.packet.size", max_packet_size);        //1byte,字符编码    short character_set_id = buff[8];    String character_set = "latin1"; //需要分析    anly.setProperty("encoding", character_set);        return anly;   }      /**    * <b> 解析数据包  </b> <br/>    未压缩:指客户端已开启压缩功能,但数据包本身不值得压缩,所以未进行压缩。<br/>    未开启压缩:指客户端未开启压缩功能,比如:./mysql 没有加-C, --compress参数。<br/>    客户端开启压缩功能后,向服务器发送数据包时,将会在包头(3+1字节)后,额外多3个字节,<br/>    表示压缩包大小,如果此值为0x000000(小端字节顺),则表示数据未压缩。     * @param buff    * @param off    * @param len    * @return 如果是最后一个包返回true    */   public boolean parse(byte[] packet,int off,int len){  //  sql = endPacket? new StringBuilder():sql;      //  _buff = (null==_buff? new byte[packetLen]: _buff);  //  _buff = packet;  //  _off = off;  //  _len = len;        if((Boolean)properties.get("compress")){     endPacket=compress(packet,off,len);    }else{     endPacket=noncompress(packet,off,len);    }          return endPacket;   }      /**    * (客户端)支持压缩    * @param packet    * @param off    * @param len    */   boolean compress(byte[] packet,int off,int len){    long tranPackLen = Util.littleBys2Uint32(packet,off+0,3);   //3 byte,传输包长度,此长度已经-7    short tranPackNo = packet[off+3];        //1 byte,传输包序号    long compressPackLen = Util.littleBys2Uint32(packet,off+4,3); //3 byte,压缩后包长度         //未压缩    if(0x000000==compressPackLen){        long srcLen = Util.littleBys2Uint32(packet,off+3+1+3,4)-1; //4byte,(包含类型信息的)源数据长度     this.requestType = packet[off+3+1+3+4];      //1byte,类型信息     _packet = packet;     _off = off+3+1+3;     _len = (int)srcLen;  //   sql.append(toSql(packet, off+3+1+3, (int)srcLen));    }else{ //已压缩     byte[] src = Util.decompress(packet,off+3+1+3,       (int)tranPackLen,(int)compressPackLen);    //n byte,src为zlib解压后的源数据     long srcLen = Util.littleBys2Uint32(src,0,4)-1;    //4byte,(包含类型信息的)源数据长度     this.requestType = src[4];         //1byte,类型信息     _packet = src;     _off = 0;     _len = (int) srcLen;  //   sql.append(toSql(src,0,(int)srcLen));    }        return 0x00==tranPackNo;   }      /**    * (客户端)不支持压缩    * @param packet    * @param off    * @param len    */   boolean noncompress(byte[] packet,int off,int len){    long tranPackLen = Util.littleBys2Uint32(packet,off+0,3);  //3 byte    short tranPackNo = packet[off+3];       //1 byte    this.requestType = packet[off+4];       //1 byte      //  sql.append(toSql(packet,off,(int)tranPackLen));    _packet = packet;    _off = off;    _len = (int)tranPackLen;        return 0x00==tranPackNo;   }      /**    * 当前包中的sql语句<br/>    * 注:这不一定是一个完整的sql语句<br/>    * @param packet    * @param off    * @param len    * @return 当requestType!=ClientRequestType.COM_QUERY时,返回""    */   String toSql(byte[] packet,int off,int len){      try {     return new String(packet,off+5,len, (String)getProperty("encoding"));    } catch (UnsupportedEncodingException e) {     throw new RuntimeException(e);       }   }      /**    * 返回sql语句 <br/>    * 只有当requestType==ClientRequestType.COM_QUERY时可用    * @return 类型不符合时,返回""    */   public String getSql(){    if(ClientRequestType.COM_QUERY!=this.requestType){     return "";    }    //  return sql.toString();    return toSql(_packet,_off,_len);   }      /**    * 返回当前sql请求类型,参见ClientRequestType    * @return 未知请求返回-1    */   public long getRequestType(){    return requestType;   }      /**    * 设置特性    * @param name    * @param value    */   public void setProperty(String name,Object value){    this.properties.put(name, value);   }      /**    * 设置特性    * @param properties    */   public void putProperty(Map<String,Object> properties){    this.properties.putAll(properties);;   }      /**    * 取特性    * @param name    * @return    */   public Object getProperty(String name){    return this.properties.get(name);   }      /**    * 返回所有特性    * @return    */   public Map<String,Object> getProperties(){    return this.properties;   }      // /**  //  * 设置传输包大小<br/>  //  * 默认值   PACKET_MAXIMUM_LENGTH  //  * @param len  //  * @see #PACKET_MAXIMUM_LENGTH  //  */  // public void setTranPacketLength(int len){  //  this.packetLen = len;  // }  }
package mysql;    /**   * 特性   * @author shanl   * @see <a href="http://dev.mysql.com/doc/internals/en/capability-flags.html#flag-CLIENT_PROTOCOL_41">http://dev.mysql.com/doc/internals/en/capability-flags.html#flag-CLIENT_PROTOCOL_41</a>    */  public interface CapabilityFlag {   long CLIENT_LONG_PASSWORD   =  0x00000001;    long CLIENT_FOUND_ROWS   =  0x00000002;   long CLIENT_LONG_FLAG   =  0x00000004;    long CLIENT_CONNECT_WITH_DB  =  0x00000008;      long CLIENT_NO_SCHEMA   =  0x00000010;   long CLIENT_COMPRESS    = 0x00000020;   long CLIENT_ODBC     =  0x00000040;   long CLIENT_LOCAL_FILES   =  0x00000080;      long CLIENT_IGNORE_SPACE  =  0x00000100;   long CLIENT_PROTOCOL_41   =  0x00000200;   long CLIENT_INTERACTIVE   =  0x00000400;   long CLIENT_SSL     =  0x00000800;      long CLIENT_IGNORE_SIGPIPE  =  0x00001000;   long CLIENT_TRANSACTIONS  =  0x00002000;   long CLIENT_RESERVED    =  0x00004000;   long CLIENT_SECURE_CONNECTION = 0x00008000;      long CLIENT_MULTI_STATEMENTS =  0x00010000;   long CLIENT_MULTI_RESULTS  =  0x00020000;   long CLIENT_PS_MULTI_RESULTS =  0x00040000;   long CLIENT_PLUGIN_AUTH   =  0x00080000;      long CLIENT_CONNECT_ATTRS      =  0x00100000;   long CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA  = 0x00200000;   long CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS  =  0x00400000;   long CLIENT_SESSION_TRACK      =  0x00800000;     long CLIENT_DEPRECATE_EOF  = 0x01000000;   }
package mysql;    /**   * 客户端请求类型   * @author shanl   * @see <a href="http://dev.mysql.com/doc/internals/en/text-protocol.html">http://dev.mysql.com/doc/internals/en/text-protocol.html</a>    */  public interface ClientRequestType {   /**(内部线程状态)*/   int COM_SLEEP     =  0x00;   /**关闭连接*/   int COM_QUIT      =  0x01;   /**切换数据库*/   int COM_INIT_DB     =  0x02;   /**SQL查询请求*/   int COM_QUERY      =  0x03;      /**获取数据表字段信息*/   int COM_FIELD_LIST     =  0x04;   /**创建数据库*/   int COM_CREATE_DB     =  0x05;   /**删除数据库*/   int COM_DROP_DB     =  0x06;   /**清除缓存*/   int COM_REFRESH     =  0x07;      /**停止服务器*/   int COM_SHUTDOWN     =  0x08;   /**获取服务器统计信息*/   int COM_STATISTICS     =  0x09;   /**获取当前连接的列表*/   int COM_PROCESS_INFO    =  0x0A;   /**(内部线程状态)*/   int COM_CONNECT     =  0x0B;      /**中断某个连接*/   int COM_PROCESS_KILL    =  0x0C;   /**保存服务器调试信息*/   int COM_DEBUG      =  0x0D;   /**测试连通性*/   int COM_PING      =  0x0E;   /**(内部线程状态)*/   int COM_TIME     =  0x0F;      /**(内部线程状态)*/   int COM_DELAYED_INSERT    =  0x10;   /**重新登陆(不断连接*/   int COM_CHANGE_USER    =   0x11;   /**获取二进制日志信息*/   int COM_BINLOG_DUMP    =  0x12;   /**获取数据表结构信息*/   int COM_TABLE_DUMP    =  0x13;      /**(内部线程状态)*/   int COM_CONNECT_OUT    =  0x14;   /**从服务器向主服务器进行注册*/   int COM_REGISTER_SLAVE   =  0x15;   /**预处理SQL语句*/   int COM_STMT_PREPARE    =  0x16;   /**执行预处理语句*/   int COM_STMT_EXECUTE    =  0x17;      /**发送BLOB类型的数据*/   int COM_STMT_SEND_LONG_DATA  = 0x18;   /**销毁预处理语句*/   int COM_STMT_CLOSE    =  0x19;   /**清除预处理语句参数缓存*/   int COM_STMT_RESET     =  0x1A;   /**设置语句选项*/   int COM_SET_OPTION     =  0x1B;      /**获取预处理语句的执行结果*/   int COM_STMT_FETCH    =  0x1C;  }


package mysql;    import java.io.ByteArrayOutputStream;  import java.io.OutputStream;  import java.util.zip.Inflater;    /**   * 为mysql分析专用工具   * @author shanl   *   */  public class Util {   /**    * Big-Endian字节数组转uint32    * @param bys    * @param off    * @param len    * @return    */   public static long bigBys2Uint32(byte[] bys,int off,int len){    long uint32 = 0;    for(int i=0,end=len-1,c=end; i<=end; i++,c--){     uint32 |= (0xff&bys[off+i])<<(8*c);    }    return uint32;     }      /**    * Little-Endian字节数组转uint32    * @param bys    * @param off    * @param len    * @return    */   public static long littleBys2Uint32(byte[] bys,int off,int len){    long uint32 = 0;    for(int i=len-1; i>=0; i--){        uint32 |= (0xff&bys[off+i])<<(8*i);    }    return uint32;   }      /**    * 适用于mysql与客户端交互时zlib解压    * @param data    * @param off    * @param len    * @param out    * @throws Exception    */   public static void decompress(byte[] data, int off, int len,OutputStream out){    Inflater decompresser = new Inflater();      decompresser.reset();    decompresser.setInput(data, off, len);    byte[] buf = new byte[1024];        try{     while(!decompresser.finished()){      int i = decompresser.inflate(buf);      out.write(buf, 0, i);      out.flush();     }    }catch(Exception ex){     throw new RuntimeException(ex);    }   }      /**    * 适用于mysql与客户端交互时zlib解压    * @param data 数据    * @param off 偏移量    * @param len 长度    * @return    */   public static byte[] decompress(byte[] data, int off, int len) {      byte[] output = null;     Inflater decompresser = new Inflater();      decompresser.reset();      //  decompresser.setInput(data);    decompresser.setInput(data, off, len);                  ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);            try {                byte[] buf = new byte[1024];                while (!decompresser.finished()) {                    int i = decompresser.inflate(buf);                    o.write(buf, 0, i);                }                output = o.toByteArray();            } catch (Exception e) {              throw new RuntimeException(e);            } finally {                try {                    o.close();                } catch (Exception e) {              }            }                decompresser.end();            return output;     }      /**    * 适用于mysql与客户端交互时zlib解压    * @param data 数据    * @param off 偏移量    * @param len 长度    * @param srcLen 源数据长度    * @return    */   public static byte[] decompress(byte[] data, int off, int len, int srcLen) {      byte[] output = null;     Inflater decompresser = new Inflater();      decompresser.reset();      //  decompresser.setInput(data);    decompresser.setInput(data, off, len);                  ByteArrayOutputStream o = new ByteArrayOutputStream(srcLen);            try {             o.reset();              byte[] buf = new byte[1024];                while (!decompresser.finished()) {                    int i = decompresser.inflate(buf);                    o.write(buf, 0, i);                }                output = o.toByteArray();            } catch (Exception e) {              throw new RuntimeException(e);            } finally {                try {                    o.close();                } catch (Exception e) {              }            }                decompresser.end();            return output;     }  }
package mysql;    /**   * 支持的字符编码   * @author shanl   * @see <a href="http://dev.mysql.com/doc/internals/en/character-set.html#packet-Protocol::CharacterSet">   * http://dev.mysql.com/doc/internals/en/character-set.html#packet-Protocol::CharacterSet</a>   */  public class CharacterSet {   /***     int big5_chinese_ci              =1;       int latin2_czech_cs              =2;       int dec8_swedish_ci              =3;       int cp850_general_ci             =4;       int latin1_german1_ci            =5;       int hp8_english_ci               =6;       int koi8r_general_ci             =7;       int latin1_swedish_ci            =8;       int latin2_general_ci            =9;       int swe7_swedish_ci             =10;       int ascii_general_ci            =11;       int ujis_japanese_ci            =12;       int sjis_japanese_ci            =13;       int cp1251_bulgarian_ci         =14;       int latin1_danish_ci            =15;       int hebrew_general_ci           =16;       int tis620_thai_ci              =18;       int euckr_korean_ci             =19;       int latin7_estonian_cs          =20;       int latin2_hungarian_ci         =21;       int koi8u_general_ci            =22;       int cp1251_ukrainian_ci         =23;       int gb2312_chinese_ci           =24;       int greek_general_ci            =25;       int cp1250_general_ci           =26;       int latin2_croatian_ci          =27;       int gbk_chinese_ci              =28;       int cp1257_lithuanian_ci        =29;       int latin5_turkish_ci           =30;       int latin1_german2_ci           =31;       int armscii8_general_ci         =32;       int utf8_general_ci             =33;       int cp1250_czech_cs             =34;       int ucs2_general_ci             =35;       int cp866_general_ci            =36;       int keybcs2_general_ci          =37;       int macce_general_ci            =38;       int macroman_general_ci         =39;       int cp852_general_ci            =40;       int latin7_general_ci           =41;       int latin7_general_cs           =42;       int macce_bin                   =43;       int cp1250_croatian_ci          =44;       int utf8mb4_general_ci          =45;       int utf8mb4_bin                 =46;       int latin1_bin                  =47;       int latin1_general_ci           =48;       int latin1_general_cs           =49;       int cp1251_bin                  =50;       int cp1251_general_ci           =51;       int cp1251_general_cs           =52;       int macroman_bin                53       int utf16_general_ci            54       int utf16_bin                   55       int cp1256_general_ci           57       int cp1257_bin                  58       int cp1257_general_ci           59       int utf32_general_ci            60       int utf32_bin                   61       int binary                      63       int armscii8_bin                64       int ascii_bin                   65       int cp1250_bin                  66       int cp1256_bin                  67       int cp866_bin                   68       int dec8_bin                    69       int greek_bin                   70       int hebrew_bin                  71       int  hp8_bin                     72       int keybcs2_bin                 73       int koi8r_bin                   74       int koi8u_bin                   75       int latin2_bin                  77       int latin5_bin                  78       int latin7_bin                  79       int cp850_bin                   80       int cp852_bin                   81       int swe7_bin                    82       int utf8_bin                    83       int big5_bin                    84       int euckr_bin                   85       int gb2312_bin                  86       int gbk_bin                     87       int sjis_bin                    88       int tis620_bin                  89       int ucs2_bin                    90       int ujis_bin                    91       int geostd8_general_ci          92       int geostd8_bin                 93       latin1_spanish_ci           94       cp932_japanese_ci           95       cp932_bin                   96       eucjpms_japanese_ci         97       eucjpms_bin                 98       cp1250_polish_ci            99       utf16_unicode_ci           101       utf16_icelandic_ci         102       utf16_latvian_ci           103       utf16_romanian_ci          104       utf16_slovenian_ci         105       utf16_polish_ci            106       utf16_estonian_ci          107       utf16_spanish_ci           108       utf16_swedish_ci           109       utf16_turkish_ci           110       utf16_czech_ci             111       utf16_danish_ci            112       utf16_lithuanian_ci        113       utf16_slovak_ci            114       utf16_spanish2_ci          115       utf16_roman_ci             116       utf16_persian_ci           117       utf16_esperanto_ci         118       utf16_hungarian_ci         119       utf16_sinhala_ci           120       ucs2_unicode_ci            128       ucs2_icelandic_ci          129       ucs2_latvian_ci            130       ucs2_romanian_ci           131       ucs2_slovenian_ci          132       ucs2_polish_ci             133       ucs2_estonian_ci           134       ucs2_spanish_ci            135       ucs2_swedish_ci            136       ucs2_turkish_ci            137       ucs2_czech_ci              138       ucs2_danish_ci             139       ucs2_lithuanian_ci         140       ucs2_slovak_ci             141       ucs2_spanish2_ci           142       ucs2_roman_ci              143       ucs2_persian_ci            144       ucs2_esperanto_ci          145       ucs2_hungarian_ci          146       ucs2_sinhala_ci            147       ucs2_general_mysql500_ci   159       utf32_unicode_ci           160       utf32_icelandic_ci         161       utf32_latvian_ci           162       utf32_romanian_ci          163       utf32_slovenian_ci         164       utf32_polish_ci            165       utf32_estonian_ci          166       utf32_spanish_ci           167       utf32_swedish_ci           168       utf32_turkish_ci           169       utf32_czech_ci             170       utf32_danish_ci            171       utf32_lithuanian_ci        172       utf32_slovak_ci            173       utf32_spanish2_ci          174       utf32_roman_ci             175       utf32_persian_ci           176       utf32_esperanto_ci         177       utf32_hungarian_ci         178       utf32_sinhala_ci           179       utf8_unicode_ci            192       utf8_icelandic_ci          193       utf8_latvian_ci            194       utf8_romanian_ci           195       utf8_slovenian_ci          196       utf8_polish_ci             197       utf8_estonian_ci           198       utf8_spanish_ci            199       utf8_swedish_ci            200       utf8_turkish_ci            201       utf8_czech_ci              202       utf8_danish_ci             203       utf8_lithuanian_ci         204       utf8_slovak_ci             205       utf8_spanish2_ci           206       utf8_roman_ci              207       utf8_persian_ci            208       utf8_esperanto_ci          209       utf8_hungarian_ci          210       utf8_sinhala_ci            211       utf8_general_mysql500_ci   223       utf8mb4_unicode_ci         224       utf8mb4_icelandic_ci       225       utf8mb4_latvian_ci         226       utf8mb4_romanian_ci        227       utf8mb4_slovenian_ci       228       utf8mb4_polish_ci          229       utf8mb4_estonian_ci        230       utf8mb4_spanish_ci         231       utf8mb4_swedish_ci         232       utf8mb4_turkish_ci         233       utf8mb4_czech_ci           234       utf8mb4_danish_ci          235       utf8mb4_lithuanian_ci      236       utf8mb4_slovak_ci          237       utf8mb4_spanish2_ci        238       utf8mb4_roman_ci           239       utf8mb4_persian_ci         240       utf8mb4_esperanto_ci       241       utf8mb4_hungarian_ci       242       utf8mb4_sinhala_ci         243            ***/  }
package test2;    import java.io.ByteArrayOutputStream;  import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream;  import java.net.InetAddress;  import java.net.InetSocketAddress;  import java.net.ServerSocket;  import java.net.Socket;  import java.net.SocketTimeoutException;  import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.zip.DataFormatException;  import java.util.zip.Inflater;    import mysql.ClientRequestType;  import mysql.MysqlAnalyse;  import mysql.Util;    /**   * 这是测试类    * @author shanl   *   */  public class Test4 {   public static void main(String[] args){  //  t1();  //  t2();  //  t3();  //  t4();  //  t5();  //  t6();  //  t7();    t8();   }      /**    * 调用MysqlAnlyse进行分析    */   static void t8(){    long packLen = 0;  //3byte    long number = 0; //1byte    long compress = 0; //3byte        File srcDir = new File("e://a//2");    File compressFile = new File(srcDir,"fc_103533_0.out.compress.3"); //uncompress  //  File compressFile = new File(srcDir,"fc_103533_0.out.compress.2"); //uncompress  //  File compressFile = new File(srcDir,"fc_103533_0.out.compress.1"); //compress  //  File compressFile = new File(srcDir,"fc_103533_0.out.decompress"); //non-compress        int readLen = 0;    byte[] buff = new byte[1024*4];        try {     FileInputStream fin = new FileInputStream(compressFile);     readLen = fin.read(buff);        fin.close();    } catch (Exception e) {       e.printStackTrace();    }        try{     MysqlAnalyse anly = new MysqlAnalyse();     anly.setProperty("compress", true);     anly.parse(buff, 0, readLen);          System.out.println(anly.getRequestType());     System.out.println(anly.getSql());    }catch(Exception e){     e.printStackTrace();    }       }      static void t7(){      byte[] capability_flags_lower = {      (byte) 0xff,(byte) 0xf7    };    byte[] capability_flags_upper = {      (byte) 7f,(byte) 0x80    };  //  byte[] bys = {  //    capability_flags_upper[1],capability_flags_upper[0],  //    capability_flags_lower[1],capability_flags_lower[0]  //  };  //  byte[] bys = {  //    capability_flags_lower[0],capability_flags_lower[1],  //    capability_flags_upper[0],capability_flags_upper[1],      //  };      byte[] bys = {          capability_flags_upper[0],capability_flags_upper[1],      capability_flags_lower[0],capability_flags_lower[1],    };  //  byte[] bys = {  ////    (byte) 0x85,(byte) 0xa6  //    (byte) 0xa5,(byte) 0xa6  //  };        long capability_flags = bigBys2Uint32(bys,0,bys.length);  //  System.out.println(capability_flags);        long compress_flag = 0x00000020;      long odbc_flag = 0x00000040;    long l = capability_flags & compress_flag;    System.out.println(l);    System.out.println(compress_flag==l);   }      static void t6(){    byte[] bys = "中".getBytes();    long i32 = bigBys2Uint32(bys,0,bys.length);    System.out.println(i32);   }      static void t5(){    long packLen = 0;  //3byte    long number = 0; //1byte    long compress = 0; //3byte        File srcDir = new File("e://a//2");    File compressFile = new File(srcDir,"fc_103533_0.out.compress.1"); //uncompress  //  File compressFile = new File(srcDir,"fc_103533_0.out.compress.2"); //compress            int readLen = 0;    byte[] buff = new byte[1024*4];        try {     FileInputStream fin = new FileInputStream(compressFile);     readLen = fin.read(buff);        fin.close();    } catch (Exception e) {       e.printStackTrace();    }        try{     packLen = littleBys2Uint32(buff,0,3);     number = littleBys2Uint32(buff,3,1);     compress = littleBys2Uint32(buff,4,3);          System.out.println("readLen: "+readLen);     System.out.println("packLen: "+packLen);     System.out.println("number: " +number);     System.out.println("compress: "+compress);    }catch(Exception e){     e.printStackTrace();    }        //decompress    long srcLen = 0;    long srcReqType = 0;    byte[] srcData = null;    try{     if(compress>0){      byte[] decompressData = Util.decompress(buff,3+1+3,readLen-7);      srcLen = Util.littleBys2Uint32(decompressData,0,4)-1;//-1去掉clientRequestType      srcReqType = Util.littleBys2Uint32(decompressData, 4, 1);      srcData = new byte[(int) srcLen];      System.arraycopy(decompressData, 5, srcData, 0, (int)srcLen);//     }else{      srcLen = Util.littleBys2Uint32(buff,3+1+3,4)-1; //-1去掉clientRequestType          srcReqType = Util.littleBys2Uint32(buff, 3+1+3+4, 1);          srcData = new byte[(int) srcLen];      System.arraycopy(buff, 3+1+3+4+1, srcData, 0, (int)srcLen);         }          System.out.println("srcLen: "+srcLen);     System.out.println("srcReqType: "+srcReqType);     if((int)srcReqType==ClientRequestType.COM_QUERY){      System.out.println("sql: "+new String(srcData));     }else{      System.out.println("non-sql request.");     }         }catch(Exception e){     e.printStackTrace();    }   }      static void t4(){    byte[] bys = {      (byte) 0xda,0x00,0x00,    };    byte[] bys1 = {      0x00,0x00,(byte) 0xda,    };        System.out.println(littleBys2Uint32(bys,0,bys.length));    System.out.println(bigBys2Uint32(bys1,0,bys1.length));   }      /**    * Big-Endian字节数组转uint32    * @param bys    * @param off    * @param len    * @return    */   static long bigBys2Uint32(byte[] bys,int off,int len){    long uint32 = 0;    for(int i=0,end=len-1,c=end; i<=end; i++,c--){     uint32 |= (0xff&bys[off+i])<<(8*c);    }    return uint32;     }      /**    * Little-Endian字节数组转uint32    * @param bys    * @param off    * @param len    * @return    */   static long littleBys2Uint32(byte[] bys,int off,int len){    long uint32 = 0;    for(int i=len-1; i>=0; i--){        uint32 |= (0xff&bys[off+i])<<(8*i);    }    return uint32;   }      static void t3(){    short[] bys = {      0xda,0x00,0x00,0x00    };        long uint32 = 0;    for(int i=bys.length-1; i>=0; i--){        uint32 |= (0xff&bys[i])<<(8*i);    }        System.out.println(uint32);  //  System.out.println(0xff&0xda);   }      public static byte[] decompress(byte[] data, int off, int len) {      byte[] output = new byte[0];     Inflater decompresser = new Inflater();      decompresser.reset();      //  decompresser.setInput(data);    decompresser.setInput(data, off, len);                  ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);            try {                byte[] buf = new byte[1024];                while (!decompresser.finished()) {                    int i = decompresser.inflate(buf);                    o.write(buf, 0, i);                }                output = o.toByteArray();            } catch (Exception e) {                output = data;                e.printStackTrace();            } finally {                try {                    o.close();                } catch (IOException e) {                    e.printStackTrace();                }            }                decompresser.end();            return output;     }      public static void decompress(byte[] data, int off, int len,OutputStream out) throws Exception{    Inflater decompresser = new Inflater();      decompresser.reset();    decompresser.setInput(data, off, len);    byte[] buf = new byte[1024];        while(!decompresser.finished()){     int i = decompresser.inflate(buf);     out.write(buf, 0, i);     out.flush();    }   }      static void t2(){    File recordDir = new File("e://a//2");    String srcFile = "fc_103533_0.out";    File cf = new File(recordDir,srcFile+".compress");  //  File cf1 = new File(recordDir,"fc_103533_0.out.compress.1");    File df = new File(recordDir,srcFile+".decompress");    int readLen = 0;    byte[] buff = new byte[1024*4];        try {     FileInputStream fin = new FileInputStream(cf);        readLen = fin.read(buff);     fin.close();       } catch (Exception e) {       e.printStackTrace();    }      //  try{  //   FileOutputStream fout = new FileOutputStream(cf1);  //   fout.write(buff,7,readLen-7);  //   fout.close();  //  }catch(Exception ex){  //   ex.printStackTrace();  //  }        try{     FileOutputStream fout = new FileOutputStream(df);     decompress(buff,7,readLen-7,fout);     fout.close();    }catch(Exception ex){     ex.printStackTrace();    }   }      static final SimpleDateFormat sdf = new SimpleDateFormat("[HH:mm:ss]");   static final SimpleDateFormat fsdf = new SimpleDateFormat("HHmmss");    /**    * 简单的代理,主要用于本地存储通信字节    */   static void t1(){    File recordDir = new File("e://a//2");    String tsip = "192.168.2.182";      int tsport = 3306;    int listenPort = 3306;    ServerSocket ss = null;      Socket fcsocket = null;    Socket tssocket = null;    int readTimeout = 1000*60*5;          try{     System.out.println("listen port:"+listenPort);     ss = new ServerSocket(listenPort);     for(int i=0;;i++){          fcsocket = ss.accept();      fcsocket.setSoTimeout(readTimeout);      System.out.println("new connected "+i);      tssocket = new Socket(tsip,tsport);      tssocket.setSoTimeout(readTimeout);          String fname_padding = fsdf.format(new Date())+"_"+i+".out";      new Recording(fcsocket,tssocket,new File(recordDir,"fc_"+fname_padding)).start();      new Recording(tssocket,fcsocket,new File(recordDir,"ts_"+fname_padding)).start();     }    }catch(Exception ex){       }   }      static class Recording extends Thread{    Socket fcsocket = null;    Socket tssocket = null;    File recordFile = null;          public Recording(Socket from,Socket to,File file){     this.fcsocket = from;     this.tssocket = to;     this.recordFile = file;    }          public void run(){     InputStream fcin = null;     OutputStream tsout = null;     int readLen = 0;     byte[] buff = new byte[1024*4];     FileOutputStream fileOut = null;          try{      recordFile.createNewFile();      fcin = fcsocket.getInputStream();      tsout = tssocket.getOutputStream();          fileOut = new FileOutputStream(recordFile);         }catch(Exception ex){      try { fileOut.close(); } catch (IOException e) { }      try { fcsocket.close(); } catch (IOException e) { }      try { tssocket.close(); } catch (IOException e) { }      return;     }             for(;;){      try{       readLen = fcin.read(buff);       tsout.write(buff,0,readLen);       tsout.flush();              fileOut.write(sdf.format(new Date()).getBytes());       fileOut.write(buff,0,readLen);       fileOut.flush();      }catch(SocketTimeoutException ste){       continue;      }catch(Exception ex){         break;      }     }          try{fileOut.close();}catch(Exception ex){}    }       }  }