- 例子: 当执行 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数据传输采用的小端法,我们不用过多处理
如果是其他协议采用大端法传输时,需要进行特殊处理。
- 源码 https://github.com/realpeanut/peanutgredis
- 其它参考
- https://github.com/gomodule/redigo
- https://github.com/golang/go/blob/master/src/strconv/atoi.go
- redis协议
有疑问加站长微信联系(非本文作者)