• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

详细介绍mysql 协议的错误包及解析

mysql 搞代码 4年前 (2022-01-09) 35次浏览 已收录 0个评论
文章目录[隐藏]

git

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

概况

mysql客户端与mysql服务端交互过程中,如果服务端遇到错误需要告知客户端则返回错误包。

mysql通信报文结构

类型 名字 描述
int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头
int<1> 序列号
string payload 报文体,长度即为前面指定的payload长度

错误包

Payload

Type Name Description
int<1> header [ff] header of the ERR packet
int<2> 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><b>email: </b>[email protected]</pre> * <pre><b>blog: </b>http://www.gaodaima.com/;/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><b>email: </b>[email protected]</pre> * <a style="color:transparent">来@源gao*daima.com搞@代#码网</a><pre><b>blog: </b>http://www.gaodaima.com/;/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><b>email: </b>[email protected]</pre> * <pre><b>blog: </b>http://www.gaodaima.com/;/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 协议的错误包及解析的内容,更多相关内容请关注搞代码(www.gaodaima.com)!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详细介绍mysql 协议的错误包及解析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址