首页 > 文章列表 > 使用go net实现简单的redis通信协议

使用go net实现简单的redis通信协议

golang
461 2022-12-17

 图解redis通信协议

请求协议:

请求协议一般格式:


*<参数数量> CR LF

$<参数 1 的字节数量> CR LF

<参数 1 的数据> CR LF

...

$<参数 N 的字节数量> CR LF

<参数 N 的数据> CR LF

例如,一个登录命令:


*2    									2-> 参数数量

$4    								4-> 字节数量

AUTH

$13

password@2018

返回结果:

+OK

实际上,发送的命令为“*2\r\n$4\r\nAUTH\r\n$13\r\npassword@2018\r\n”

测试代码:


package main



import (

	"bufio"

	"fmt"

	"net"

	"strconv"

	"testing"

	"time"

)

type Conn struct {

	// Shared

	conn    net.Conn

	// Read

	br          *bufio.Reader

	// Write

	bw           *bufio.Writer

}





func (c *Conn) Write(cmd string, args ...string) error {

	_, err := c.bw.WriteString("*" + strconv.Itoa(1 + len(args)) + "\r\n")

	if err != nil {

		return err

	}

	_, err =c.bw.WriteString("$" + strconv.Itoa(len(cmd)) + "\r\n" + cmd + "\r\n")

	if err != nil {

		return err

	}

	for _, v := range args {

		_, err :=c.bw.WriteString("$" + strconv.Itoa(len(v)) + "\r\n" + v + "\r\n")

		if err != nil {

			return err

		}

	}

	err = c.bw.Flush()

	if err != nil {

		return err

	}

	return nil

}



func TestDail(t *testing.T) {

	conn,err  := net.Dial("tcp","127.0.0.1:6379")

	if err != nil {

		panic(err)

	}



	var c = &Conn{

		conn: conn,

		br : bufio.NewReader(conn),

		bw: bufio.NewWriter(conn),

	}

	err = c.Write("AUTH","password@2018")

	if err != nil {

		panic(err)

	}

	p, err := c.br.ReadSlice('\n')

	if err != nil {

		panic(err)

	}

	fmt.Println(string(p))

	err = c.Write("SELECT", "5")

	if err != nil {

		panic(err)

	}

	p, err = c.br.ReadSlice('\n')

	if err != nil {

		panic(err)

	}

	fmt.Println(string(p))

	err = c.Write("keys","*")

	if err != nil {

		panic(err)

	}

	buffer := make([]byte, 4096)

	n, err := c.br.Read(buffer)

	if err != nil {

		panic(err)

	}

	fmt.Println(string(buffer[:n]))

}

运行结果

+OK

+OK

*9

$4

set2

$1

s

$4

set3

$7

string3

$4

int1

$4

test

$7

string2

$7

string1

$7

string4