git
https://github.com/sea-boat/mysql-protocol
Présentation
Lors de l'interaction entre le client mysql et le serveur mysql, si le serveur rencontre une erreur et doit en informer le client, un paquet d'erreur sera renvoyé.
Structure du message de communication MySQL
Type |
Nom |
Description th > |
int<3> |
la longueur de la charge utile |
est stockée en fonction de l'octet de poids faible en premier, 3 mots La charge utile de la strophe et le numéro de séquence de 1 octet sont combinés dans un en-tête de message |
int<1> |
Numéro de série |
类型 |
名字 |
描述 |
int<3> |
payload长度 |
按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头 |
int<1> |
序列号 |
|
string |
payload |
报文体,长度即为前面指定的payload长度 |
chaîne |
charge utile |
Corps du message, la longueur est la longueur de la charge utile précédemment spécifiée | tr>
Package d'erreurs
Charge utile
Type |
Nom |
Description |
int<1> td> |
en-tête |
[ff] en-tête du paquet ERR |
int<2> |
error_code | code d'erreur
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 |
|
si capacités & CLIENT_PROTOCOL_41 { |
| tr>
string[1] |
sql_state_marker |
marqueur de l'état SQL |
string[ 5] |
sql_state |
État SQL |
|
} |
|
chaîne |
error_message |
message d'erreur lisible par l'homme |
table>Plus de détails : http://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html- Erreur de fonctionnement des paquets
Classe de package d'erreur/**
*
* @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";
}
}
Copier après la connexion
Outil de conversion hexadécimale/**
*
* @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();
}
}
Copier après la connexion
Test de génération de paquets d'erreur/**
*
* @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);
}
}
Copier après la connexion
Ce qui précède est une introduction détaillée au paquet d'erreur et à l'analyse du protocole mysql. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (. www.php.cn ) !