文档章节

MySQL通信协议栈Java实现-(1)数据类型

张哈希_
 张哈希_
发布于 2016/04/24 11:41
字数 867
阅读 19
收藏 0

最新官网MySQL通信协议栈说明地址:http://dev.mysql.com/doc/internals/en/client-server-protocol.html

1. 数据类型

1.1 整型

1.1.1 定长整型

定长整型最小位在最前,一共有如下几种定长整型:

int<1>
int<2>
int<3>
int<4>
int<6>
int<8>

例如:int<3>表示1为:

01 00 00

1.1.2 长度编码整型

int<lenenc>

根据长度不同,长度编码整型有不同的编码:
如果值<251,则存储为1字节整型
如果值≥251并<2^16,则存储为以0xfc开头+2字节整型
如果值≥2^16并<2^24,则存储为以0xfd开头+3字节整型
如果值≥2^24并<2^64,则存储为以0xfe开头+8字节整型
举例:

fa       -- 250
fc fb 00 -- 251

1.1.3 实现

Int.java:

package io.timberwolf.net.protocols.mysql.data;

import com.google.common.base.Preconditions;

import java.nio.ByteBuffer;

/** * MySQL protocol DataType - Integer Types * * @author Hash Zhang * @version 0.0.0 * @see @http://dev.mysql.com/doc/internals/en/integer.html */
public class Int {
    //定长整型数据编码解码
    public static int writeLength1(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x100);
        buffer.put((byte) num);
        return 1;
    }

    public static int readLength1(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        return (int) buffer.get();
    }

    public static int writeLength2(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x10000);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        return 2;
    }

    public static int readLength2(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        int result = (int) buffer.get();
        result += ((int) buffer.get()) << 8;
        return result;
    }

    public static int writeLength3(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x1000000);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        return 3;
    }

    public static int readLength3(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        int result = (int) buffer.get();
        result += ((int) buffer.get()) << 8;
        result += ((int) buffer.get()) << 16;
        return result;
    }

    public static int writeLength4(ByteBuffer buffer, long num) {
        Preconditions.checkArgument(num < 0x100000000L);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        return 4;
    }

    public static long readLength4(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        return result;
    }

    public static int wrietLength6(ByteBuffer buffer, long num) {
        Preconditions.checkArgument(num <= 0x1000000000000L);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        buffer.put((byte) (num >>> 32));
        buffer.put((byte) (num >>> 40));
        return 6;
    }

    public static long readLength6(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        result += ((long) buffer.get()) << 32;
        result += ((long) buffer.get()) << 40;
        return result;
    }

    public static int writeLength8(ByteBuffer buffer, long num) {
        buffer.put((byte) num);
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        buffer.put((byte) (num >>> 32));
        buffer.put((byte) (num >>> 40));
        buffer.put((byte) (num >>> 48));
        buffer.put((byte) (num >>> 56));
        return 8;
    }

    public static long readLength8(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        result += ((long) buffer.get()) << 32;
        result += ((long) buffer.get()) << 40;
        result += ((long) buffer.get()) << 48;
        result += ((long) buffer.get()) << 56;
        return result;
    }

    //长度编码整型数据编码解码
    public static int writeLengthEncoded(ByteBuffer buffer, long num) {
        if (num < 0xfb) {
            writeLength1(buffer, (int) num);
            return 1;
        } else if (num < 0x10000) {
            buffer.put((byte) 0xfc);
            writeLength2(buffer, (int) num);
            return 3;
        } else if (num < 0x10000) {
            buffer.put((byte) 0xfd);
            writeLength3(buffer, (int) num);
            return 4;
        } else {
            buffer.put((byte) 0xfe);
            writeLength8(buffer, num);
            return 9;
        }
    }

    public static long readLengthEncoded(ByteBuffer buffer) {
        int num = readLength1(buffer);
        long result = 0;
        if(num < 0xfb){
            result += num;
        } else if(num == 0xfc){
            result += readLength2(buffer);
        } else if(num == 0xfd){
            result += readLength3(buffer);
        } else{
            result +=readLength8(buffer);
        }
        return result;
    }
}


1.2 字符串类型

1.2.1定长字符串

定长字符串拥有已知的固定的长度

1.2.2null截止字符串

字符串用[00]字节截止

1.2.3变长字符串

字符串长度由另一域值决定

1.2.4长度编码字符串

长度编码整型+定长字符串(长度为前面整型代表的数值)

1.2.5剩余长度字符串

如果字符串是包最后一个元素,它的长度可以由包长度减去当前位置决定。

string<lenenc>  Protocol::LengthEncodedString
string<fix> Protocol::FixedLengthString
string<var> Protocol::VariableLengthString:
string<EOF> Protocol::RestOfPacketString
string<NUL> Protocol::NulTerminatedString
package io.timberwolf.net.protocols.mysql.data;

import com.google.common.base.Preconditions;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/** * MySQL protocol DataType - String Types * * @author Hash Zhang * @version 0.0.0 * @see @http://dev.mysql.com/doc/internals/en/string.html */
public class Str {
    public static int lengthEncoded(ByteBuffer buffer, String string, String charSet) throws UnsupportedEncodingException {
        Preconditions.checkNotNull(string);
        int length = string.getBytes(charSet).length;
        length += Int.writeLengthEncoded(buffer,length);
        buffer.put(string.getBytes(charSet));
        return length;
    }
}

© 著作权归作者所有

张哈希_
粉丝 7
博文 42
码字总数 67907
作品 0
房山
程序员
私信 提问
基于Android平台的无线传感器网络(ZigBee)监控系统

过去包括将来,从别人开源项目上和博客学到太多,实在是很欣赏开源的精神。这段时间,review了下做过的东西,毕业后不再做这个方向的东西了。陆续也有不少网上或者低届的同学问我讨要论文相关...

Change_Ty
2013/05/30
0
44
从多核硬件架构,看Java内存模型

在了解Java内存模型之前,先来看一下多核硬件架构。 我们应该都知道,计算机在执行程序的时候,每条指令都是在CPU中执行的,而执行的时候,又免不了要和数据打交道。而计算机上面的数据,是存...

消失er
2018/09/02
0
0
MySQL JDBC StreamResult通信原理浅析

使用MySQL JDBC读取过较大数据量的人应该清楚(例如超过1GB),在读取的时候内存很可能会Java堆内存溢出,而我们的解决方案是statement.setFetchSize(Integer.MIN_VALUE)并确保游标是只读向前...

阿里云云栖社区
2018/10/18
0
0
解决Fiddler不能监听Java HttpURLConnection请求的方法

在默认情况下,Fiddler不能监听Java HttpURLConnection请求。究其原因,Java的网络通信协议栈可能浏览器的通信协议栈略有区别,Fiddler监听Http请求的原理是在应用程序和操作系统网络通信层之...

小克898
2013/05/18
0
0
Apache Thrift介绍

Thrift是为了解决facebook系统中各系统之间大数据量的传输通讯以及系统之间语言环境不同需要跨平台这一特性而创造的。所以thrift可以支持多种程序语言,例如: C++, C#, Cocoa, Erlang, Haske...

吕坤
2013/02/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

typescript 接口 函数类型 可索引类型

函数类型 可索引类型 数字索引签名 字符串索引签名 数字索引签名返回值 必须是 字符串索引签名返回值的子集 只读索引签名

lilugirl
今天
3
0
Oracle SQL语法实例合集

如需转载请注明出处https://my.oschina.net/feistel/blog/3052024 目的:迅速激活Oracle SQL 参考:《Oracle从入门到精通》 ------------------------------------------------------------......

LoSingSang
今天
2
0
增加 PostgreSQL 服务进程的最大打开文件数

https://serverfault.com/questions/628610/increasing-nproc-for-processes-launched-by-systemd-on-centos-7 要在systemd的配置里加才行...

helloclia
今天
2
0
组合模式在商品分类列表中的应用

在所有的树形结构中最适合的设计模式就是组合模式,我们看看常用商品分类中如何使用。 先定义一个树形结构的商品接口 public interface TreeProduct { List<TreeProduct> allProducts(...

算法之名
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部