概况
mysql客户端与mysql服务端交互过程中,当服务端完成客户端的某命令时则会返回OK包。
mysql通信报文结构
类型 | 名字 | 描述 |
---|---|---|
int<3> | payload长度 | 按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 |
int<1> | 序列号 | |
string | payload | 报文体,长度即为前面指定的payload长度 |
OK包
Payload
Type | Name | Description |
---|---|---|
int<1> | header | [00] or [fe] the OK packet header |
int | affected_rows | affected rows |
int | last_insert_id | last insert-id |
if capabilities & CLIENT_PROTOCOL_41 { | ||
int<2> | status_flags | Status Flags |
int<2> | warnings | number of warnings |
}elseif capabilities & CLIENT_TRANSACTIONS { | ||
int<2> | status_flags | Status Flags |
} | ||
if capabilities & CLIENT_SESSION_TRACK { | ||
string | info | human readable status information |
if status_flags & SERVER_SESSION_STATE_CHANGED | ||
string | session_state_changes | session state info |
} | ||
} else { | ||
string | info | human readable status information |
} |
Status Flags
Flag | Value |
SERVER_STATUS_IN_TRANS | 0x0001 |
SERVER_STATUS_AUTOCOMMIT | 0x0002 |
SERVER_MORE_RESULTS_EXISTS | 0x0008 |
SERVER_STATUS_NO_GOOD_INDEX_USED | 0x0010 |
SERVER_STATUS_NO_INDEX_USED | 0x0020 |
SERVER_STATUS_CURSOR_EXISTS | 0x0040 |
SERVER_STATUS_LAST_ROW_SENT | 0x0080 |
SERVER_STATUS_DB_DROPPED | 0x0100 |
SERVER_STATUS_NO_BACKSLASH_ESCAPES | 0x0200 |
SERVER_STATUS_metaDATA_CHANGED | 0x0400 |
SERVER_QUERY_WAS_SLOW | 0x0800 |
SERVER_PS_OUT_PARAMS | 0x1000 |
SERVER_STATUS_IN_TRANS_READONLY | 0x2000 |
SERVER_SESSION_STATE_CHANGED | 0x4000 |
OK包操作
OK包类public class OKPacket extends MySQLPacket { public static final byte HEADER = 0x00; public static final byte[] OK = new byte[] { 7, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0 }; public byte header = HEADER; public long affectedRows; public long insertId; public int serverStatus; public int warningCount; public byte[] message; public void read(byte[] data) { MySQLMessage mm = new MySQLMessage(data); packetLength = mm.readUB3(); packetId = mm.read(); header = mm.read(); affectedRows = mm.readLength(); insertId = mm.readLength(); serverStatus = mm.readUB2(); warningCount = mm.readUB2(); if (mm.hasRemaining()) { this.message = mm.readBytesWithLength(); } } public void write(ByteBuffer buffer) { BufferUtil.writeUB3(buffer, calcPacketSize()); buffer.put(packetId); buffer.put(header); BufferUtil.writeLength(buffer, affectedRows); BufferUtil.writeLength(buffer, insertId); BufferUtil.writeUB2(buffer, serverStatus); BufferUtil.writeUB2(buffer, warningCount); if (message != null) { BufferUtil.writeWithLength(buffer, message); } } @Override public int calcPacketSize() { int i = 1; i += BufferUtil.getLength(affectedRows); i += BufferUtil.getLength(insertId); i += 4; if (message != null) { i += BufferUtil.getLength(message); } return i; } @Override protected String getPacketInfo() { return "MySQL OK Packet"; }}
测试类
public class OKPacketTest { @Test public void produce() { OKPacket ok = new OKPacket(); ok.packetId = 2; ok.affectedRows = 0; ok.insertId = 0; ok.serverStatus = 2; ok.warningCount = 0; ByteBuffer buffer = ByteBuffer.allocate(256); ok.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); OKPacket ok2 = new OKPacket(); ok2.read(bytes); //auth ok assertTrue(result.equals("0700000200000002000000")); }}