main函数为入口,ListenAndServeWithSignal接收address和handle接口,server.MakeHandler()实现了handle接口
func main() {
config.SetUpConfig("redis.conf")
tcp.ListenAndServeWithSignal(
"0.0.0.0:8989",
server.MakeHandler())
}
package tcp
import (
"context"
"gRedis/interface/tcp"
"log"
"net"
"os"
"os/signal"
"sync"
"syscall"
)
func ListenAndServeWithSignal(address string, handler tcp.Handler) {
closeChan := make(chan struct{})
// 这里是golang的信号,在这里接收系统的信号,比如ctrl+c就会往一个无缓冲的管道里写入数据
// 然后通知服务器关闭
sigCh := make(chan os.Signal)
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
go func() {
sig := <-sigCh
switch sig {
case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
closeChan <- struct{}{}
}
}()
listener, err := net.Listen("tcp", address)
if err !=nil {
log.Println("出错了")
}
ListenAndServe(listener,handler,closeChan)
}
func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan struct{}) {
//这个接收信号 根据信号来进行关闭
go func() {
<-closeChan
_ = listener.Close()
_ = handler.Close()
}()
defer func() {
_ = listener.Close()
_ = handler.Close()
}()
ctx := context.Background()
var waitDone sync.WaitGroup
for {
conn, err := listener.Accept()
if err != nil {
return
}
log.Println("accept link")
waitDone.Add(1)
go func() {
defer func() {
waitDone.Done()
}()
//最外层for循环就是循环接收数据,
//这里就是每次循环开启一个协程,然后处理完数据利用defer结束
handler.Handler(ctx,conn)
}()
}
waitDone.Wait()
}
package server
import (
"bufio"
"context"
"gRedis/interface/db"
"io"
"log"
"net"
)
type Handle struct {
db db.DB
}
func MakeHandler() *Handle {
return &Handle{
}
}
func (this *Handle) Handler(ctx context.Context,conn net.Conn) {
reader := bufio.NewReader(conn)
for {
readString, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
log.Println("connection close")
} else {
log.Println(err)
}
return
}
b := []byte(readString)
conn.Write(b)
}
}
func (this *Handle) Close() error {
return nil
}
package db
import "gRedis/interface/redis"
type DB interface {
Exec(client redis.Connection, args [][]byte) redis.Reply
}
package redis
type Reply interface {
ToBytes() []byte
}
package tcp
import (
"context"
"net"
)
type Handler interface {
Handler(ctx context.Context,conn net.Conn)
Close() error
}