mirror of
https://gitee.com/lauix/HFish
synced 2025-05-12 04:48:01 +08:00
130 lines
2.5 KiB
Go
130 lines
2.5 KiB
Go
|
package redis
|
|||
|
|
|||
|
import (
|
|||
|
"net"
|
|||
|
"bufio"
|
|||
|
"strings"
|
|||
|
"strconv"
|
|||
|
"HFish/utils/try"
|
|||
|
"HFish/core/report"
|
|||
|
)
|
|||
|
|
|||
|
var kvData map[string]string
|
|||
|
|
|||
|
func Start(addr string) {
|
|||
|
kvData = make(map[string]string)
|
|||
|
|
|||
|
//建立socket,监听端口
|
|||
|
netListen, _ := net.Listen("tcp", addr)
|
|||
|
|
|||
|
defer netListen.Close()
|
|||
|
|
|||
|
for {
|
|||
|
conn, err := netListen.Accept()
|
|||
|
if err != nil {
|
|||
|
continue
|
|||
|
}
|
|||
|
arr := strings.Split(conn.RemoteAddr().String(), ":")
|
|||
|
id := report.ReportRedis(arr[0], conn.RemoteAddr().String()+" 已经连接")
|
|||
|
|
|||
|
go handleConnection(conn, id)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//处理 Redis 连接
|
|||
|
func handleConnection(conn net.Conn, id int64) {
|
|||
|
for {
|
|||
|
str := parseRESP(conn)
|
|||
|
|
|||
|
switch value := str.(type) {
|
|||
|
case string:
|
|||
|
report.ReportUpdateRedis(id, "&&"+str.(string))
|
|||
|
|
|||
|
if len(value) == 0 {
|
|||
|
goto end
|
|||
|
}
|
|||
|
conn.Write([]byte(value))
|
|||
|
case []string:
|
|||
|
if value[0] == "SET" || value[0] == "set" {
|
|||
|
// 模拟 redis set
|
|||
|
|
|||
|
try.Try(func() {
|
|||
|
key := string(value[1])
|
|||
|
val := string(value[2])
|
|||
|
kvData[key] = val
|
|||
|
|
|||
|
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1]+" "+value[2])
|
|||
|
|
|||
|
}).Catch(func() {
|
|||
|
// 取不到 key 会异常
|
|||
|
})
|
|||
|
|
|||
|
conn.Write([]byte("+OK\r\n"))
|
|||
|
} else if value[0] == "GET" || value[0] == "get" {
|
|||
|
// 模拟 redis get
|
|||
|
key := string(value[1])
|
|||
|
val := string(kvData[key])
|
|||
|
|
|||
|
valLen := strconv.Itoa(len(val))
|
|||
|
str := "$" + valLen + "\r\n" + val + "\r\n"
|
|||
|
|
|||
|
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
|
|||
|
|
|||
|
conn.Write([]byte(str))
|
|||
|
} else {
|
|||
|
try.Try(func() {
|
|||
|
report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
|
|||
|
}).Catch(func() {
|
|||
|
report.ReportUpdateRedis(id, "&&"+value[0])
|
|||
|
})
|
|||
|
|
|||
|
conn.Write([]byte("+OK\r\n"))
|
|||
|
}
|
|||
|
break
|
|||
|
default:
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
end:
|
|||
|
conn.Close()
|
|||
|
}
|
|||
|
|
|||
|
// 解析 Redis 协议
|
|||
|
func parseRESP(conn net.Conn) interface{} {
|
|||
|
r := bufio.NewReader(conn)
|
|||
|
line, err := r.ReadString('\n')
|
|||
|
if err != nil {
|
|||
|
return ""
|
|||
|
}
|
|||
|
|
|||
|
cmdType := string(line[0])
|
|||
|
cmdTxt := strings.Trim(string(line[1:]), "\r\n")
|
|||
|
|
|||
|
switch cmdType {
|
|||
|
case "*":
|
|||
|
count, _ := strconv.Atoi(cmdTxt)
|
|||
|
var data []string
|
|||
|
for i := 0; i < count; i++ {
|
|||
|
line, _ := r.ReadString('\n')
|
|||
|
cmd_txt := strings.Trim(string(line[1:]), "\r\n")
|
|||
|
c, _ := strconv.Atoi(cmd_txt)
|
|||
|
length := c + 2
|
|||
|
str := ""
|
|||
|
for length > 0 {
|
|||
|
block, _ := r.Peek(length)
|
|||
|
if length != len(block) {
|
|||
|
|
|||
|
}
|
|||
|
r.Discard(length)
|
|||
|
str += string(block)
|
|||
|
length -= len(block)
|
|||
|
}
|
|||
|
|
|||
|
data = append(data, strings.Trim(str, "\r\n"))
|
|||
|
}
|
|||
|
return data
|
|||
|
default:
|
|||
|
return cmdTxt
|
|||
|
}
|
|||
|
}
|