0

0

详细介绍mysql 协议的服务端握手包及对其解析

黄舟

黄舟

发布时间:2018-05-12 16:41:36

|

3280人浏览过

|

来源于php中文网

原创

概况

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

client              
server   
|------connect---- >|
   |                   |
   |<----handshake-----|
   |                   |
   |                   |
   |                   |

mysql通信报文结构

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

生成初始握手包

  1. 定义版

/**
 * 
 * @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>proxy's version.</p>
 */public interface Versions {

    byte PROTOCOL_VERSION = 10;    byte[] SERVER_VERSION = "5.6.0-snapshot".getBytes();
}
  1. 随机数工具

/**
 * 
 * @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>a random util .</p>
 */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;
    }

}
  1. mysql包基类

/**
 * 
 * @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>MySQLPacket is mysql's basic packet.</p><div class="aritcle_card flexRow">
                                                        <div class="artcardd flexRow">
                                                                <a class="aritcle_card_img" href="/ai/1345" title="智川X-Agent"><img
                                                                                src="https://img.php.cn/upload/ai_manual/000/000/000/175679972846726.png" alt="智川X-Agent"  onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
                                                                <div class="aritcle_card_info flexColumn">
                                                                        <a href="/ai/1345" title="智川X-Agent">智川X-Agent</a>
                                                                        <p>中科闻歌推出的一站式AI智能体开发平台</p>
                                                                </div>
                                                                <a href="/ai/1345" title="智川X-Agent" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
                                                        </div>
                                                </div>
 */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();
    }

}
  1. 握手包类

/**
 * 
 * @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>AuthPacket means mysql initial handshake packet .</p>
 */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";
    }

}
  1. 服务端能力类

/**
 * 
 * @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>server capabilities .</p>
 */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;

}
  1. 测试类

/**
 * 
 * @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 handshake packet.</p>
 */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;
    }

}

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

223

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

458

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

169

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

246

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

34

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.5万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 847人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号