概况

mysql客户端登陆到mysql服务端需要一个交互的过程,这里先看服务端给客户端发送的初始握手包。如下,client通过socket连接到server指定的端口后,server将往client发送初始握手包。服务端会根据不同的服务版本和不同的配置返回不同的初始化握手包。client

server

|------connect---- >|

| |

|

| |

| |

| |

mysql通信报文结构类型名字描述int<3>payload长度按照the least significant byte first存储,3个字节的payload和1个字节的序列号组合成报文头

int<1>序列号

stringpayload报文体,长度即为前面指定的payload长度

初始握手包

HandshakeV10协议如下1 [0a] protocol version

string[NUL] server version

4 connection id

string[8] auth-plugin-data-part-1

1 [00] filler

2 capability flags (lower 2 bytes)

if more data in the packet:

1 character set

2 status flags

2 capability flags (upper 2 bytes)

if capabilities & CLIENT_PLUGIN_AUTH {

1 length of auth-plugin-data

} else {

1 [00]

}

string[10] reserved (all [00])

if capabilities & CLIENT_SECURE_CONNECTION {

string[$len] auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))

if capabilities & CLIENT_PLUGIN_AUTH {

if version >= (5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2) {

string[EOF] auth-plugin name

} elseif version >= 5.5.10 or >= 5.6.2 {

string[NUL] auth-plugin name

}

}

生成初始握手包定义版/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

proxy's version.

*/public interface Versions {

byte PROTOCOL_VERSION = 10; byte[] SERVER_VERSION = "5.6.0-snapshot".getBytes();

}随机数工具/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

a random util .

*/public class RandomUtil {

private static final byte[] bytes = { '1', '2', '3', '4', '5', '6', '7',

'8', '9', '0', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',

'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v',

'b', 'n', 'm', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',

'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V',

'B', 'N', 'M' };

private static final long multiplier = 0x5DEECE66DL;

private static final long addend = 0xBL;

private static final long mask = (1L << 48) - 1;

private static final long integerMask = (1L << 33) - 1;

private static final long seedUniquifier = 8682522807148012L;

private static long seed;

static {

long s = seedUniquifier + System.nanoTime();

s = (s ^ multiplier) & mask;

seed = s;

} public static final byte[] randomBytes(int size) {

byte[] bb = bytes;

byte[] ab = new byte[size];

for (int i = 0; i < size; i++) {

ab[i] = randomByte(bb);

} return ab;

} private static byte randomByte(byte[] b) {

int ran = (int) ((next() & integerMask) >>> 16);

return b[ran % b.length];

} private static long next() {

long oldSeed = seed;

long nextSeed = 0L;

do {

nextSeed = (oldSeed * multiplier + addend) & mask;

}

while (oldSeed == nextSeed);

seed = nextSeed;

return nextSeed;

}

}mysql包基类/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

MySQLPacket is mysql's basic packet.

*/public abstract class MySQLPacket {

/**

* none, this is an internal thread state

*/

public static final byte COM_SLEEP = 0; /**

* mysql_close

*/

public static final byte COM_QUIT = 1; /**

* mysql_select_db

*/

public static final byte COM_INIT_DB = 2; /**

* mysql_real_query

*/

public static final byte COM_QUERY = 3; /**

* mysql_list_fields

*/

public static final byte COM_FIELD_LIST = 4; /**

* mysql_create_db (deprecated)

*/

public static final byte COM_CREATE_DB = 5; /**

* mysql_drop_db (deprecated)

*/

public static final byte COM_DROP_DB = 6; /**

* mysql_refresh

*/

public static final byte COM_REFRESH = 7; /**

* mysql_shutdown

*/

public static final byte COM_SHUTDOWN = 8; /**

* mysql_stat

*/

public static final byte COM_STATISTICS = 9; /**

* mysql_list_processes

*/

public static final byte COM_PROCESS_INFO = 10; /**

* none, this is an internal thread state

*/

public static final byte COM_CONNECT = 11; /**

* mysql_kill

*/

public static final byte COM_PROCESS_KILL = 12; /**

* mysql_dump_debug_info

*/

public static final byte COM_DEBUG = 13; /**

* mysql_ping

*/

public static final byte COM_PING = 14; /**

* none, this is an internal thread state

*/

public static final byte COM_TIME = 15; /**

* none, this is an internal thread state

*/

public static final byte COM_DELAYED_INSERT = 16; /**

* mysql_change_user

*/

public static final byte COM_CHANGE_USER = 17; /**

* used by slave server mysqlbinlog

*/

public static final byte COM_BINLOG_DUMP = 18; /**

* used by slave server to get master table

*/

public static final byte COM_TABLE_DUMP = 19; /**

* used by slave to log connection to master

*/

public static final byte COM_CONNECT_OUT = 20; /**

* used by slave to register to master

*/

public static final byte COM_REGISTER_SLAVE = 21; /**

* mysql_stmt_prepare

*/

public static final byte COM_STMT_PREPARE = 22; /**

* mysql_stmt_execute

*/

public static final byte COM_STMT_EXECUTE = 23; /**

* mysql_stmt_send_long_data

*/

public static final byte COM_STMT_SEND_LONG_DATA = 24; /**

* mysql_stmt_close

*/

public static final byte COM_STMT_CLOSE = 25; /**

* mysql_stmt_reset

*/

public static final byte COM_STMT_RESET = 26; /**

* mysql_set_server_option

*/

public static final byte COM_SET_OPTION = 27; /**

* mysql_stmt_fetch

*/

public static final byte COM_STMT_FETCH = 28; /**

* mysql packet length

*/

public int packetLength; /**

* mysql packet id

*/

public byte packetId; /**

* calculate mysql packet length

*/

public abstract int calcPacketSize(); /**

* mysql packet info

*/

protected abstract String getPacketInfo(); @Override

public String toString() { return new StringBuilder().append(getPacketInfo()).append("{length=")

.append(packetLength).append(",id=").append(packetId)

.append('}').toString();

}

}握手包类/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

AuthPacket means mysql initial handshake packet .

*/public class HandshakePacket extends MySQLPacket {

private static final byte[] FILLER_13 = new byte[] { 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0 };

public byte protocolVersion;

public byte[] serverVersion;

public long threadId;

public byte[] seed;

public int serverCapabilities;

public byte serverCharsetIndex;

public int serverStatus;

public byte[] restOfScrambleBuff;

public void read(byte[] data) {

MySQLMessage mm = new MySQLMessage(data);

packetLength = mm.readUB3();

packetId = mm.read();

protocolVersion = mm.read();

serverVersion = mm.readBytesWithNull();

threadId = mm.readUB4();

seed = mm.readBytesWithNull();

serverCapabilities = mm.readUB2();

serverCharsetIndex = mm.read();

serverStatus = mm.readUB2();

mm.move(13);

restOfScrambleBuff = mm.readBytesWithNull();

} @Override

public int calcPacketSize() { int size = 1;

size += serverVersion.length;// n

size += 5;// 1+4

size += seed.length;// 8

size += 19;// 1+2+1+2+13

size += restOfScrambleBuff.length;// 12

size += 1;// 1

return size;

} public void write(ByteBuffer buffer) {

BufferUtil.writeUB3(buffer, calcPacketSize());

buffer.put(packetId);

buffer.put(protocolVersion);

BufferUtil.writeWithNull(buffer, serverVersion);

BufferUtil.writeUB4(buffer, threadId);

BufferUtil.writeWithNull(buffer, seed);

BufferUtil.writeUB2(buffer, serverCapabilities);

buffer.put(serverCharsetIndex);

BufferUtil.writeUB2(buffer, serverStatus);

buffer.put(FILLER_13);

BufferUtil.writeWithNull(buffer, restOfScrambleBuff);

} @Override

protected String getPacketInfo() {

return "MySQL Handshake Packet";

}

}服务端能力类/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

server capabilities .

*/public interface Capabilities {

// new more secure passwords

int CLIENT_LONG_PASSWORD = 1; // Found instead of affected rows

int CLIENT_FOUND_ROWS = 2; // Get all column flags

int CLIENT_LONG_FLAG = 4; // One can specify db on connect

int CLIENT_CONNECT_WITH_DB = 8; // Don't allow database.table.column

int CLIENT_NO_SCHEMA = 16; // Can use compression protocol

int CLIENT_COMPRESS = 32; // Odbc client

int CLIENT_ODBC = 64; // Can use LOAD DATA LOCAL

int CLIENT_LOCAL_FILES = 128; // Ignore spaces before '('

int CLIENT_IGNORE_SPACE = 256; // New 4.1 protocol This is an interactive client

int CLIENT_PROTOCOL_41 = 512; // This is an interactive client

int CLIENT_INTERACTIVE = 1024; // Switch to SSL after handshake

int CLIENT_SSL = 2048; // IGNORE sigpipes

int CLIENT_IGNORE_SIGPIPE = 4096; // Client knows about transactions

int CLIENT_TRANSACTIONS = 8192; // Old flag for 4.1 protocol

int CLIENT_RESERVED = 16384; // New 4.1 authentication

int CLIENT_SECURE_CONNECTION = 32768; // Enable/disable multi-stmt support

int CLIENT_MULTI_STATEMENTS = 65536; // Enable/disable multi-results

int CLIENT_MULTI_RESULTS = 131072;

}测试类/**

*

* @author seaboat

* @date 2016-09-25

* @version 1.0

*

email: 849586227@qq.com

*

blog: http://www.php.cn/;/pre>

*

test handshake packet.

*/public class HandshakePacketTest {

private final static byte[] hex = "0123456789ABCDEF".getBytes(); @Test

public void produce() {

byte[] rand1 = RandomUtil.randomBytes(8);

byte[] rand2 = RandomUtil.randomBytes(12);

byte[] seed = new byte[rand1.length + rand2.length];

System.arraycopy(rand1, 0, seed, 0, rand1.length);

System.arraycopy(rand2, 0, seed, rand1.length, rand2.length);

HandshakePacket hs = new HandshakePacket();

hs.packetId = 0;

hs.protocolVersion = Versions.PROTOCOL_VERSION;

hs.serverVersion = Versions.SERVER_VERSION;

hs.threadId = 1000;

hs.seed = rand1;

hs.serverCapabilities = getServerCapabilities();

hs.serverCharsetIndex = (byte) (CharsetUtil.getIndex("utf8") & 0xff);

hs.serverStatus = 2;

hs.restOfScrambleBuff = rand2;

ByteBuffer buffer = ByteBuffer.allocate(256);

hs.write(buffer);

buffer.flip();

byte[] bytes = new byte[buffer.remaining()];

buffer.get(bytes, 0, bytes.length);

String result = Bytes2HexString(bytes);

assertTrue(Integer.valueOf(result.substring(0,2),16)==result.length()/2-4);

} 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();

} protected int getServerCapabilities() {

int flag = 0;

flag |= Capabilities.CLIENT_LONG_PASSWORD;

flag |= Capabilities.CLIENT_FOUND_ROWS;

flag |= Capabilities.CLIENT_LONG_FLAG;

flag |= Capabilities.CLIENT_CONNECT_WITH_DB;

flag |= Capabilities.CLIENT_ODBC;

flag |= Capabilities.CLIENT_IGNORE_SPACE;

flag |= Capabilities.CLIENT_PROTOCOL_41;

flag |= Capabilities.CLIENT_INTERACTIVE;

flag |= Capabilities.CLIENT_IGNORE_SIGPIPE;

flag |= Capabilities.CLIENT_TRANSACTIONS;

flag |= Capabilities.CLIENT_SECURE_CONNECTION;

return flag;

}

}

mysql握手_详细介绍mysql 协议的服务端握手包及对其解析相关推荐

  1. mysql innodb 锁类型_详细介绍MySQL InnoDB存储引擎各种不同类型的锁

    本文中,我们详细介绍MySQLInnoDB存储引擎各种不同类型的锁,以及不同SQL语句分别会加什么样的锁. 阅读提示 1.本文所参考的MySQL文档版本是8.0,做实验的MySQL版本是8.0.13 ...

  2. mysql 全局变量_详细讲解mysql全局变量与局部变量

    通常在服务器启动时,会将每个全局变量初始化为其默认值(我们可以通过命令行或选项文件中指定的选项更改这些默认值),然后服务器还为每个连接的客户端维护一组会话变量,客户端的会话变量在连接时使用相应全局变量 ...

  3. mysql geo 函数_【后端开发】地理位置geo处理之mysql函数的详细介绍(附代码)

    本篇文章给大家带来的内容是关于地理位置geo处理之mysql函数的详细介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目前越来越多的业务都会基于LBS,附近的人,外卖位 ...

  4. mysql eof_详细介绍mysql 协议的EOF包及解析

    git https://github.com/sea-boat/mysql-protocol 概况 mysql的EOF包用于标明查询结果的结尾. mysql通信报文结构类型名字描述int<3&g ...

  5. mysql geo_地理位置geo处理之mysql函数的详细介绍(附代码)

    本篇文章给大家带来的内容是关于地理位置geo处理之mysql函数的详细介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目前越来越多的业务都会基于LBS,附近的人,外卖位 ...

  6. php socket 握手,python Socket之客户端和服务端握手详细介绍

    这篇文章主要为大家详细介绍了python Socket之客户端和服务端握手,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 简单的学习下利用socket来建立客户端和服务端之间的连接并且发送数据 1 ...

  7. 了解MySQL(超详细的MySQL工作原理 体系结构)

    了解MySQL(超详细的MySQL工作原理 体系结构) 1.MySQL体系结构 2.MySQL内存结构 3.MySQL文件结构 4.innodb体系结构 一.了解MySQL前你需要知道的 引擎是什么: ...

  8. etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具

    etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具 参考 [拉钩教育 etcd核心原理]

  9. mysql如何设置多节点_详细介绍Mysql5.7从节点设置多线程主从复制的办法

    软件安装:装机软件必备包 SQL是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言.在使用它时,只需要发出& ...

最新文章

  1. 改进AI/ML部署的5种方法
  2. leetcode算法题--字符串相乘
  3. MySQL之性能优化解说
  4. 读书笔记:季羡林关于如何做研究学问的心得
  5. Rabbitmq消息可靠投递和重复消费等问题解决方案
  6. 使用AWS DMS 升级Postgre 10到12
  7. 首届全国大学生工程训练综合能力竞赛圆满落幕
  8. c++代码格式化工具神器AStyle介绍
  9. Ubuntu下安装UDK
  10. UE_GPU Driven Pipeline Mesh Shader(meshlet)
  11. 服务器 raid配置
  12. logrotate 管理日志文件不生效
  13. 北京市居民公共交通出行特征分析
  14. 如何建立异地容灾备份体系
  15. 面试了10几家公司后被怼,逼的我把源码都吃透了,最终成功入职阿里
  16. MIPS反汇编拆炸弹
  17. ARM Cortex-A系列编程指南之ARMv8 A -- 第二章 ARMv8 A架构和处理器
  18. 电商不仅仅有CRUD——0基础了解电商中的引流工具谷歌GMC
  19. Python解析百度地图各省市经纬度(二)
  20. 见她之前再见她,冥冥之中有天意

热门文章

  1. 区块链当前的发展现状
  2. 简易双人坦克大战制作流程(一)
  3. SCI论文发表中需要经历哪些过程?
  4. google 学术使用技巧
  5. 在office如何安装翻译软件插件
  6. 还在为网速烦恼?你可能没有使用华为云CDN加速服务
  7. 智能硬件行业产品经理
  8. Elasticsearch2.3.4集群安装指南
  9. [机器学习笔记] 将数据拆分成训练集和测试集的几种方法
  10. 专业技术职务代码-GBT8561-2001