navicat 如果存在_Navicat? 数据库 HTTP 隧道通信协议

本文详细解析了Navicat通过HTTP隧道进行数据库通信的请求格式、回复格式,包括数据库状态头、查询状态头等各个部分的结构和内容,以及示例和练习,帮助理解Navicat的通信协议。
摘要由CSDN通过智能技术生成

dc5e6bc891c4a622694257980249d191.png

基于 Navicat™ 15 提供的隧道脚本,与 Navicat™ 版权无关的研究。

保留所有权利。未经作者许可不得转载。

请求格式

Navicat™ HTTP 代理基于简单 HTTP。用 通信使用 POST 以 multipart/form-data 为基准提交数据操作信息。

每次提交的表单需要包含如下的数据:

b998e3f076bb94af05bac29c213be457.png

其中,host 不需要包含端口号,q[] 为可空。actn 只有两种值:

  • C:表示建立数据库连接
  • Q:表示执行数据库查询

理论上,Navicat™ 自身没有限制单次请求的数据尺寸,但是在实现中限制为 2,097,152 字节(2MiB)。

回复格式

Navicat™ 协议的回复是二进制格式的数据。数据类型分为头和块两种,基本顺序为:

  1. 数据库状态头
  2. 数据库消息块
  3. 查询状态头
  4. 查询消息块
  5. 查询返回表头
  6. 查询返回行块

其中,数据库指代数据库服务器实例(Database Instance),查询指代每一个发送到服务器的独立 SQL 查询(Query),返回的结果中,每个查询结果数据使用字节 x01 分割,使用 x00 表示结束。

块相对于头来说更加简单,块由正文长度前缀以及正文组成。

如果正文小于 254 个字节,那么头的长度前缀为长度的字符形式。否则写入 xFE,后跟正文长度的 16 进制 32 位无符号整型。正文直接是原始数据的 UTF-8 字符数组。

注意,块大小限制在 4,294,967,295 个字节( 4GiB)长度。

数据库状态头

其中,数据库状态头是所有回复的第一组内容。数据库状态头由下面几段二进制组成(所有的数据都是大端序

  1. 32 位无符号整型 1111
  2. 16 位无符号整型 202
  3. 32 位无符号整型错误状态码
  4. 6 个 x00 填充

其中,错误码只有两个数字:

  • 1 表示存在错误
  • 0 表示不存在错误。

如果存在错误(错误码为 1)那么便以数据块的形式写入错误资讯。如果没有错误,那么将写入查询状态头。

查询状态头

查询状态头说明了数据查询的概要信息,包括是否出错,影响行数,最后插入行标识以及后续跟随的行数据的规模(多少条)以及尺寸(多少字段),组成:

  1. 32 位无符号整型错误码
  2. 32 位无符号整型受影响行数
  3. 32 位无符号整型最后插入行 ID
  4. 32 位无符号整型返回行字段数量
  5. 32 位无符号整型返回行数量
  6. 12 个 x00 填充

其中,错误码只有两个数字:

  • 1 表示存在错误
  • 0 表示不存在错误。

如果存在错误(错误码为 1)那么便以数据块的形式写入错误资讯。如果没有错误,那么将写入查询返回表头。

查询返回表头

查询返回表头说明了后面跟随的表的字段信息。数据由多个数据块构成,典型数据块是:

  1. 表头名块
  2. 表名块

块后跟

  1. 32 位无符号整型数据库类型代号(OID)
  2. 32 位无符号整型数据库字段描述符
  3. 32 位无符号整型类型尺寸

值得注意的是,字段与字段之间是没有显著分隔字符的。所有的数据都会严格按照顺序写入。

查询返回行块

该块内容直接按照左右上下的顺序写入单元格数据。除 NULL 单元格写入 xFF 外,每个单元格数据均以数据块的形式写入。

示例

获取连接信息

00000000  00 00 04 57 00 ca 00 00 00 00 00 00 00 00 00 00      W            
00000010  05 4d 79 53 51 4c 0d 76 69 61 20 54 43 50 2f 49    MySQL via TCP/I
00000020  50 20 31 30 10 53 51 4c 69 6e 6b 20 66 6f 72 20   P 10 SQLink for 
00000030  4d 79 53 51 4c                                    MySQL
  • 序列 [00000000]
  1. 32 位无符号整型 111100 00 04 57
  2. 16 位无符号整型 20200 ca
  3. 32 位无符号整型错误状态码 → 00 00 00 00
  4. 6 个 x00 填充 → 00 00 00 00 00 00
32 位无符号整型为 4 字节,32 比特。16 位无符号整型为 2 字节,16 比特。
  • 序列 [00000010 - 00000030]
  1. 数据库 Host 信息块 MySQL,长度 5 → 05 + 4d 79 53 51 4c
  2. 数据库协议信息块 via TCP/IP 10,长度 13 → 0d + 76 69 61 20 54 43 50 2f 49 50 20 31 30
  3. 数据库版本块 SQLink for MySQL,长度 16 → 10 + 53 51 4c 69 6e 6b 20 66 6f 72 20 4d 79 53 51 4c

查询 SELECT * FROM AA.test123 LIMIT 0,1000

00000000  00 00 04 57 00 ca 00 00 00 00 00 00 00 00 00 00      W            
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03                   
00000020  00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00                   
00000030  02 69 64 00 00 00 00 03 00 00 50 03 00 00 00 0b    id       P     
00000040  04 6e 61 6d 65 00 00 00 00 fc 00 00 00 10 00 02    name           
00000050  ff fd 07 63 6f 6d 6d 65 6e 74 00 00 00 00 fc 00      comment      
00000060  00 00 10 00 02 ff fd 01 31 03 79 65 70 ff 01 32           1 yep  2
00000070  03 79 65 70 ff 00                                  yep  

数据返回预览:

0060734b3155415679fbcd2222bae20d.png

查询状态头

  • 序列 [00000000] 与上方示例相同,不再赘述。
  • 序列 [00000010] - [00000020]
  1. 32 位无符号整型错误码:无错误,0 → 00 00 00 00
  2. 32 位无符号整型受影响行数:SELECT 语句没有更新,0 → 00 00 00 00
  3. 32 位无符号整型最后插入行 ID:SELECT 语句没有更新,0 → 00 00 00 00
  4. 32 位无符号整型返回行字段数量,3 → 00 00 00 03
  5. 32 位无符号整型返回行数量 2 → 00 00 00 02
  6. 12 个 x00 填充 → 00 00 00 00 00 00 00 00 00 00 00 00

查询返回表头

  • [00000030]
  1. id,长度 2,类型 int02 + 69 64 + 00
  2. OID 3 + 描述符 20483 + 长度 11 → 00 00 00 03 + 00 00 50 03 + 00 00 00 0b
  • [00000040] - [00000050]
  1. name,长度 4,类型 text04 + 6e 61 6d 65 + 00
  2. OID 252 + 描述符 16 + 长度 196605 → 00 00 00 fc + 00 00 00 10 + 00 02 ff fd
  • [00000050] - [00000060]
  1. comment,长度 7,类型 text07 + 63 6f 6d 6d 65 6e 74 + 00
  2. OID 252 + 描述符 16 + 长度 196605 → 00 00 00 fc + 00 00 00 10 + 00 02 ff fd
OID 以及描述符来自数据库官方,一般数据库驱动会提供。

查询返回行块

  • [00000060] - [00000070]

ad1a07b1f177c04041a060a7c3acfe29.png

分隔符

没有更多结果集(ResultSet),所以以 00 结束。


练习

没错,上个 知乎 读篇文章居然还要做练习!

Navicat™ 兼容的一段二进制:

00000000  00 00 04 57 00 ca 00 00 00 00 00 00 00 00 00 00      W            
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                   
00000020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                   
00000030  00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00                   
00000040  00 08 00 00 00 02 00 00 00 00 00 00 00 00 00 00                   
00000050  00 00 03 6d 69 64 00 00 00 00 17 00 00 00 00 00      mid          
00000060  00 00 00 04 6e 61 6d 65 00 00 00 04 13 00 00 00       name        
00000070  00 00 00 00 c8 04 73 6c 75 67 00 00 00 04 13 00         slug      
00000080  00 00 00 00 00 00 c8 04 74 79 70 65 00 00 00 04           type    
00000090  13 00 00 00 00 00 00 00 10 0b 64 65 73 63 72 69             descri
000000a0  70 74 69 6f 6e 00 00 00 04 13 00 00 00 00 00 00   ption           
000000b0  00 c8 05 63 6f 75 6e 74 00 00 00 00 17 00 00 00      count        
000000c0  00 00 00 00 00 05 6f 72 64 65 72 00 00 00 00 17         order     
000000d0  00 00 00 00 00 00 00 00 06 70 61 72 65 6e 74 00            parent 
000000e0  00 00 00 17 00 00 00 00 00 00 00 00 01 31 0c e9                1  
000000f0  bb 98 e8 ae a4 e5 88 86 e7 b1 bb 07 64 65 66 61     认分类 defa
00000100  75 6c 74 08 63 61 74 65 67 6f 72 79 18 e5 8f aa   ult category 只
00000110  e6 98 af e4 b8 80 e4 b8 aa e9 bb 98 e8 ae a4 e5   是一个默认 
00000120  88 86 e7 b1 bb 01 30 01 31 01 30 01 32 06 e6 8a     类 0 1 0 2   
00000130  80 e6 9c af 09 74 65 63 68 6e 69 63 61 6c 08 63    术 technical c
00000140  61 74 65 67 6f 72 79 ff 01 32 01 32 01 30 00      ategory  2 2 0

请尝试分析表格数据并标注类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值