2019-08-07 13:16:23 +08:00
|
|
|
|
package redis
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"net"
|
|
|
|
|
"bufio"
|
|
|
|
|
"strings"
|
|
|
|
|
"strconv"
|
|
|
|
|
"HFish/utils/try"
|
|
|
|
|
"HFish/core/report"
|
2019-08-08 09:52:05 +08:00
|
|
|
|
"HFish/utils/log"
|
2019-08-07 13:16:23 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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()+" 已经连接")
|
2019-08-08 09:52:05 +08:00
|
|
|
|
log.Pr("Redis", arr[0], "已经连接")
|
2019-08-07 13:16:23 +08:00
|
|
|
|
|
|
|
|
|
go handleConnection(conn, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//处理 Redis 连接
|
|
|
|
|
func handleConnection(conn net.Conn, id int64) {
|
|
|
|
|
for {
|
|
|
|
|
str := parseRESP(conn)
|
|
|
|
|
|
|
|
|
|
switch value := str.(type) {
|
|
|
|
|
case string:
|
2019-08-09 10:13:54 +08:00
|
|
|
|
go report.ReportUpdateRedis(id, "&&"+str.(string))
|
2019-08-07 13:16:23 +08:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2019-08-09 10:13:54 +08:00
|
|
|
|
go report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1]+" "+value[2])
|
2019-08-07 13:16:23 +08:00
|
|
|
|
|
|
|
|
|
}).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"
|
|
|
|
|
|
2019-08-09 10:13:54 +08:00
|
|
|
|
go report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
|
2019-08-07 13:16:23 +08:00
|
|
|
|
|
|
|
|
|
conn.Write([]byte(str))
|
|
|
|
|
} else {
|
|
|
|
|
try.Try(func() {
|
2019-08-09 10:13:54 +08:00
|
|
|
|
go report.ReportUpdateRedis(id, "&&"+value[0]+" "+value[1])
|
2019-08-07 13:16:23 +08:00
|
|
|
|
}).Catch(func() {
|
2019-08-09 10:13:54 +08:00
|
|
|
|
go report.ReportUpdateRedis(id, "&&"+value[0])
|
2019-08-07 13:16:23 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|