详细介绍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 分享