golang实现redis协议之10进制ascii码转义

realPeanut · · 577 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  • 例子: 当执行 get key时 假设 返回 100000000

抓包返回如下

24 39 0d 0a 31 30 30 30 30 30 30 30 30 0d 0a

  • 其中第一个字节24为16进制的ASCII码$

代表批量回复

  • 第二个字节为16进制的ASCII码9

代表value值为9位ASCII码,9字节

  • 0d 0a 代表\r\n
  • 31 30 30 30 30 30 30 30 30 为1、0、0、0、0 0、0、0、0的ASCII码
  • 拼接后即为100000000

以上是分析的抓包数据


  • 在实际开发过程中如下golang程序中,rs得到的实际值是10进制的ASCII码,数据类型为[]byte
    r := bufio.NewReader(rc.Conn.conn)

    p, err := r.ReadSlice(redis_cut)
    ... 
    ln, err := io.ReadFull(r, rs)
[36 57 13 10] [49 48 48 48 48 48 48 48 48]
  • 因为要知道36($)后的57代表的实际字符,而且要转为int,这样我们才能只要要从io.buffer中读取多少字节,所以我们要进行以下操作
  • ascii做算数减法,减去ascii码'0'(ascii 十进制为48)
func ParseLen(p []byte) (int, error) {

fmt.Println(p)
    if len(p) == 0 {

        return -1, nil
    }

    if p[0] == '-' && len(p) == 2 && p[1] == '1' {
        return -1, nil
    }

    var n int
    for _, b := range p {
        n *= 10
        if b < '0' || b > '9' {
            return -1, nil
        }
        n += int(b - '0')
        //ascii运算相当于57-48
    }
  • 总结在我们自己写10进制ascii转码int时,可以用下面的方法
    zjd := make([]byte,2)
    t[0] = 57
    println(t[0] - 48 )//方法1
    println(t[0] - '0' )//方法2

redis数据传输采用的小端法,我们不用过多处理
如果是其他协议采用大端法传输时,需要进行特殊处理。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:realPeanut

查看原文:golang实现redis协议之10进制ascii码转义

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

577 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传