package net import ( "bufio" "fmt" "net" "pro2d/src/common" "pro2d/src/components/logger" ) type Head struct { Length int32 Cmd int32 ErrCode int32 PreField int32 } type Connection struct { net.Conn Id int Server *Server scanner *bufio.Scanner writer *bufio.Writer WBuffer chan []byte RBuffer chan *MsgPkg Quit chan *Connection } type MsgPkg struct { Head *Head Body []byte Conn *Connection } func NewConn(id int, conn net.Conn, s *Server) *Connection { return &Connection{ Id: id, Conn: conn, Server: s, scanner: bufio.NewScanner(conn), writer: bufio.NewWriter(conn), WBuffer: make(chan []byte), RBuffer: make(chan *MsgPkg), Quit: make(chan *Connection), } } func (c *Connection) write() { defer c.Quiting() for msg := range c.WBuffer { if _, err := c.writer.Write(msg); err != nil { fmt.Println("write fail err: " + err.Error()) return } if err := c.writer.Flush(); err != nil { fmt.Println("write Flush fail err: " + err.Error()) return } } } func (c *Connection) read() { defer c.Quiting() c.scanner.Split(ParseMsg) for c.scanner.Scan() { req, err := DecodeMsg(c.scanner.Bytes()) if err != nil { return } req.Conn = c //得到需要处理此条连接的workerID workerID := c.Id % c.Server.SConf.WorkerPoolSize //将请求消息发送给任务队列 c.Server.TaskQueue[workerID] <- req //备注,可以在当前协程处理当条请求(如下, 实现很简单,已经删除),也可以丢到协程池里处理任务(如上),还未对比效果。 //c.Server.OnRecv(req) } if err := c.scanner.Err(); err != nil { fmt.Printf("scanner.err: %s\n", err.Error()) c.Quiting() return } } func (c *Connection) Start() { go c.write() go c.read() } func (c *Connection) Stop() { close(c.RBuffer) close(c.WBuffer) c.Conn.Close() } func (c *Connection) Quiting() { c.Server.OnClose(c) } func (c *Connection) SendMsgByCode(errCode int32, cmd int32, data []byte){ h := &Head{ Length: int32(common.HEADLEN + len(data)), Cmd: cmd, ErrCode: errCode, PreField: 0, } pkg := &MsgPkg{ Head: h, Body: data, } buf, err := EncodeMsg(pkg) if err != nil { logger.Error("SendMsg error: %v", err) return } c.WBuffer <- buf }