func (a *WSAgent) Run() { a.Trace("run...") msgChan := make(chan []byte, 1024) a.innerMsgChan = make(chan []byte, 1024) a.needClose = make(chan bool) go func() { defer utils.PrintPanicStack() for { if a.conn == nil { a.Error("WSAgent 连接为nil") a.needClose <- true return } data, err := a.conn.ReadMsg() if err != nil { a.Debug("读取消息错误: %v", err) a.needClose <- true return } msgChan <- data } }() for { var data []byte var err error select { case data = <-msgChan: case data = <-a.innerMsgChan: case <-a.needClose: { log.Error("WSAgent 发生错误") a.Close() return } } if a.handlerMessage != nil { _, err = a.handlerMessage(a, data, a.UserData) if err != nil { a.Debug("[handlerMessage]protobuf handle msg error %v", err) //WHY: 解析错误需要跳出循环吗? //break } } else if a.protobufProcessor != nil { _, err = a.protobufProcessor.Handler(a, data, a.UserData) if err != nil { a.Debug("[protobufProcessor]protobuf handle msg error %v", err) //WHY: 解析错误需要跳出循环吗? //break } } } }
//实现net.http.handler接口 //每次HTTP请求的时候被调用,用于产生链接 func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer utils.PrintPanicStack() log.Trace("new connect from %s(url:%s)", r.RemoteAddr, r.RequestURI) if r.Method != "GET" { http.Error(w, "Method not allowed", 405) return } conn, err := handler.upgrader.Upgrade(w, r, nil) if err != nil { log.Debug("upgrade error: %v", err) return } handler.wg.Add(1) defer handler.wg.Done() handler.mutexConns.Lock() if handler.conns == nil { handler.mutexConns.Unlock() conn.Close() log.Debug("upgrade error: nil") return } if len(handler.conns) >= handler.maxConnNum { handler.mutexConns.Unlock() conn.Close() log.Debug("too many connections") return } handler.conns[conn] = struct{}{} handler.mutexConns.Unlock() wsConn := newWSConn(conn, handler.pendingWriteNum) agent := handler.newAgent(wsConn) agent.Run() // cleanup wsConn.Close() handler.mutexConns.Lock() delete(handler.conns, conn) handler.mutexConns.Unlock() agent.OnClose() }