golang网关(3)-- 协程应用

86 阅读1分钟

本系列注重于应用,至于内功心法(如:SCP进程模型啊,线程啊,用户态啊,内核态啊等等等)请读者自行补充

goroutine 是 golang 实现的协程,其特点是在语言层面就支持,使用起来非常方便

程序协程简单拓扑图

协程.png

上源码

tcp.go

func StartCoreTCPServer() {
	// 2S 之后才启动SOCKET服务
	time.Sleep(time.Second * 2)

	err := coreListener.Start()
	if logs.ErrorProcess(err, "tcp start error") {
		return
	}

	logs.Show("start tcp service @%s", port)

	// 启动心跳检查
	// 关闭默认心跳。2022-04-22
	base.Go(heartBeatJob)
//接收多个用户
	for {
		// 其他业务处理,如:黑名单,限流等
		//处理用户请求, 新建一个协程
		base.Go(HandleConn, fd, conn)
                // 其他业务
	}
// HandleConn 处理用户请求
func HandleConn(id uint32, conn net.Conn) {

	//声明一个临时缓冲区,用来存储被截断的数据
	tmpBuffer := make([]byte, 0)

	//声明一个管道用于接收解包的数据
	readerChannel := make(chan []byte, 128)

	//函数调用完毕,自动关闭conn
	defer func() {
		close(readerChannel)
		//closeClient(id, nil)
	}()

	// 新启一个协程,处理具体的业务请求
	base.Go(reader, id, conn.RemoteAddr().String(), readerChannel)

	buf := make([]byte, 1024)

	for {
		if !clientManager.HasID(id) {
			return
		}
		//读取用户数据
		n, err := conn.Read(buf)
		if err != nil {
			closeClient(id, err)
			return
		}
		tmpBuffer = tcp.CheckBuffer(append(tmpBuffer, buf[:n]...), readerChannel)
	}
}
func reader(id uint32, addr string, readerChannel chan []byte) {
	for {
		select {
		case data, ok := <-readerChannel:
			if !ok || data == nil {
				return
                                // 业务处理
			}
                }
           }
  }