MySQL協議分析
參考資料:
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 >
* 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 >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 >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 >
* 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){}
}
}
}
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!