詳細介紹mysql 協議的錯誤包及解析

git

https://github.com/sea-boat/mysql-protocol

概況

mysql客戶端與mysql服務端交互過程中,如果服務端遇到錯誤需要告知客戶端則返回錯誤包。

mysql通信報文結構

類型 名字 描述
int payload長度 按照the least significant byte first存儲,3個字節的payload和1個字節的序列號組合成報文頭
int 序列號
string payload 報文體,長度即為前面指定的payload長度

錯誤包

Payload

Type Name Description
int header [ff] header of the ERR packet
int error_code error-code
if capabilities & CLIENT_PROTOCOL_41 {
string[1] sql_state_marker marker of the SQL State
string[5] sql_state SQL State
}
string error_message human readable error message

更多詳情 :?http://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html

錯誤包操作

  1. 錯誤包類

/**  ?*?  ?*?@author?seaboat  ?*?@date?2016-09-25  ?*?@version?1.0  ?*?<pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com

?*?

<b>blog: </b>http://www.php.cn/;/pre>   * <p>mysql error packet.</p>   */public class ErrorPacket extends MySQLPacket {      public static final byte header = (byte) 0xff;          private static final byte SQLSTATE_MARKER = (byte) '#';          private static final byte[] DEFAULT_SQLSTATE = "HY000".getBytes();          public int errno;          public byte mark = SQLSTATE_MARKER;          public byte[] sqlState = DEFAULT_SQLSTATE;          public byte[] message;          public void read(byte[] data) {          MySQLMessage mm = new MySQLMessage(data);          packetLength = mm.readUB3();          packetId = mm.read();          mm.read();          errno = mm.readUB2();                  if (mm.hasRemaining() && (mm.read(mm.position()) == SQLSTATE_MARKER)) {              mm.read();              sqlState = mm.readBytes(5);          }          message = mm.readBytes();      }          public void write(ByteBuffer buffer) {              int size = calcPacketSize();          BufferUtil.writeUB3(buffer, size);          buffer.put(packetId);          buffer.put(header);          BufferUtil.writeUB2(buffer, errno);          buffer.put(mark);          buffer.put(sqlState);          buffer.put(message);      }    @Override      public int calcPacketSize() {              int size = 9;// 1 + 2 + 1 + 5          if (message != null) {              size += message.length;          }                  return size;      }          @Override      protected String getPacketInfo() {              return "MySQL Error Packet";      }    }
  1. 十六進制轉換工具

/**  ?*?  ?*?@author?seaboat  ?*?@date?2016-09-25  ?*?@version?1.0  ?*?<pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com

?*?

<b>blog: </b>http://www.php.cn/;/pre>   * <p>hex transform util.</p>   */public class HexUtil {      private final static byte[] hex = "0123456789ABCDEF".getBytes();          public static String Bytes2HexString(byte[] b) {              byte[] buff = new byte[2 * b.length];              for (int i = 0; i < b.length; i++) {              buff[2 * i] = hex[(b[i] >> 4) & 0x0f];              buff[2 * i + 1] = hex[b[i] & 0x0f];          }        return new String(buff);      }    public static String str2HexStr(String str) {              char[] chars = "0123456789ABCDEF".toCharArray();          StringBuilder sb = new StringBuilder("");                  byte[] bs = str.getBytes();                  int bit;                  for (int i = 0; i < bs.length; i++) {              bit = (bs[i] & 0x0f0) >> 4;              sb.append(chars[bit]);              bit = bs[i] & 0x0f;              sb.append(chars[bit]);          }        return sb.toString();      }  }
  1. 錯誤包生成測試

/**  ?*?  ?*?@author?seaboat  ?*?@date?2016-09-25  ?*?@version?1.0  ?*?<pre class="brush:php;toolbar:false"><b>email: </b>849586227@qq.com

?*?

<b>blog: </b>http://www.php.cn/;/pre>   * <p>test auth packet.</p>   */public class ErrorPacketTest {      @Test      public void produce() {          ErrorPacket err = new ErrorPacket();          err.packetId = 1;          err.errno = 32322;          err.message = "sorry".getBytes();          ByteBuffer buffer = ByteBuffer.allocate(256);          err.write(buffer);          buffer.flip();        byte[] bytes = new byte[buffer.remaining()];          buffer.get(bytes, 0, bytes.length);          String result = HexUtil.Bytes2HexString(bytes);          System.out.println(result);          assertTrue(Integer.valueOf(result.substring(0, 2), 16) == result                  .length() / 2 - 4);            ErrorPacket err2 = new ErrorPacket();          err2.read(bytes);          assertTrue(err2.errno == 32322);          assertTrue(err2.message.length == "sorry".getBytes().length);      }    }

?以上就是詳細介紹mysql 協議的錯誤包及解析的內容,更多相關內容請關注PHP中文網(www.php.cn)!

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享