mysql 协议的错误包及解析

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>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://blog.csdn.net/wangyangzhizhou</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>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://blog.csdn.net/wangyangzhizhou</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>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://blog.csdn.net/wangyangzhizhou</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);
    }

}

========广告时间========

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。

为什么写《Tomcat内核设计剖析》

=========================

时间: 2024-07-30 12:19:21

mysql 协议的错误包及解析的相关文章

mysql 协议的OK包及解析

git https://github.com/sea-boat/mysql-protocol 概况 mysql客户端与mysql服务端交互过程中,当服务端完成客户端的某命令时则会返回OK包. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为前面指定的paylo

mysql 协议的EOF包及解析

git https://github.com/sea-boat/mysql-protocol 概况 mysql的EOF包用于标明查询结果的结尾. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为前面指定的payload长度 EOF包 Payload Type

mysql 协议的query包及解析

git https://github.com/sea-boat/mysql-protocol 概况 mysql客户端可以用query包向服务端发送一个基于文本查询. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为前面指定的payload长度 query包 P

mysql 协议的ResultsetRow包及解析

git https://github.com/sea-boat/mysql-protocol 概况 ResultsetRow包属于服务端返回ResultSet时的其中一部分包,用于描述结果集的行记录. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为前面指定的

mysql 协议的认证包及解析

git https://github.com/sea-boat/mysql-protocol 概况 mysql客户端登陆到mysql服务端需要一个交互的过程,首先服务端给客户端发送的初始握手包,客户端接收到握手包后向服务端返回认证包.如下,这里分析下认证包. client server |-------connect------>| | | |<-----handshake------| | | |---authentication--->| | | mysql通信报文结构 类型 名字

mysql 协议的ColumnDefinition包及解析

git https://github.com/sea-boat/mysql-protocol 概况 ColumnDefinition包属于服务端返回ResultSet时的其中一部分包,用于描述结果集的字段信息. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为

mysql 协议的ColumnCount包及解析

git https://github.com/sea-boat/mysql-protocol 概况 ColumnCount包属于服务端返回ResultSet时的其中一部分包. mysql通信报文结构 类型 名字 描述 int<3> payload长度 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 int<1> 序列号 string payload 报文体,长度即为前面指定的payload长度 Col

MYSQL CLENT/SERVER数据包传输及net packet buffer作用解析

原创:转载请说明出处 水平有限再加上源码的复杂性,难免出现错误,请共同研究予以纠正 本文参考源码: Net_serv.cc(主要参考) Mysql.h.pp Mysql_socket.h Violite.h Viosocket.c Vio.c 参考书籍: 深入理解MYSQL核心技术 MYSQL核心内幕 internals-en MYSQL官方手册 LINUX系统编程手册 注意:    1.本文将主要解析非压缩MYSQL NET包,而尽量不考虑压缩的MYSQL NET包来减小难度    2.本文主

对已经获取的.pcap网络数据包的解析

问题描述 对已经获取的.pcap网络数据包的解析 网络数据包进行解析并进行资源文件(图片.文本.视频等)统计,网上都是获得网络协议tcp,udp的信息,怎样才能统计数据包里的图片,文本信息呢?