Hello 大家好,我是 roseduan,上一次给大家分享了 rosedb 项目当中所涉及到的一些数据结构,有链表、哈希表、跳表、有序集合,内容比较的硬核,你可以温习一下前面的几篇文章:
今天的内容比较轻松,相信你一定可以完全掌握,参考视频在文章的底部。
我们常常使用 redis cli 来操作 redis ,比如 set、get 等等,那你知道它是怎么实现的吗?
这里我以 rosedb 为例,为你实现一个具备类似功能的命令行操作。首先来看一下完成后的效果示例:
在项目 rosedb/cmd/server 下面,有一个 main.go ,使用 go run main.go 命令来启动它:
然后在 rosedb/cmd/cli 下面,同样执行 go run main.go 来启动一个客户端,启动完成之后,就能够进行命令操作了,比如 set、get 等等:
接下来再看具体的实现,其实也比较简单,分为了两部分,服务端和客户端。
服务端
服务端的本质,就是启动一个 TCP 服务器,监听一个端口,主要代码如下:
func (s *Server) Listen(addr string) {
var err error
// 启动 TCP 服务器
s.listener, err = net.Listen("tcp", addr)
if err != nil {
log.Printf("tcp listen err: %+v\n", err)
return
}
log.Println("rosedb is running, ready to accept connections.")
// 获取客户端的连接
for {
select {
case <-s.done:
return
default:
conn, err := s.listener.Accept()
if err != nil {
continue
}
// 处理连接
go s.handleConn(conn)
}
}
}
服务端还做一件事情,就是获取客户端的连接,然后取出命令执行,并获取到执行的结果。
获取到结果之后,再返回到客户端,你可以看这个 handleConn 方法:
func (s *Server) handleConn(conn net.Conn) {
defer conn.Close()
for {
// ...
// 读取客户端的数据
size := binary.BigEndian.Uint32(b[:4])
if size > 0 {
data := make([]byte, size)
_, err := bufReader.Read(data)
if err != nil {
log.Printf("read cmd data err: %+v\n", err)
break
}
// 执行命令,获取到结果
cmdAndArgs := reg.FindAllString(string(data), -1)
reply := s.handleCmd(cmdAndArgs[0], cmdAndArgs[1:])
info := wrapReplyInfo(reply)
// 将结果写回到客户端
_, err = conn.Write(info)
if err != nil {
log.Printf("write reply err: %+v\n", err)
}
}
}
}
客户端
客户端的工作,就是与服务端建立连接,然后获取用户的输入,并且传到服务端。
然后从服务端获取到运行的结果,并将结果打印出来,关键代码如下:
func main() {
flag.Parse()
addr := fmt.Sprintf("%s:%d", *host, *port)
// 连接到服务器
conn, err := net.Dial("tcp", addr)
if err != nil {
log.Println("tcp dial err: ", err)
return
}
// ... 不重要的代码就忽略了
// 命令数据传到服务端
wInfo := wrapCmdInfo(cmd)
_, err := conn.Write(wInfo)
if err != nil {
fmt.Println(err)
}
// 获取服务端的结果,并打印出来
reply := readReply(conn)
fmt.Println(reply)
}
}
}
这就是全部的实现了,是不是非常简单呢?当然我目前实现的这个版本,还是比较简陋的,很多命令都还没有支持,可完善的地方还是挺多的。
视频参考
题图:from wallheaven.cc
本文分享自 roseduan写字的地方 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!