//---------------------------------------------------------- Hub processing func HubAgent(incoming chan []byte, conn net.Conn) { config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } hostid := atomic.AddInt32(&_host_genid, 1) // forward buffer forward := make(chan []byte, MAXCHAN) // output buffer output := make(chan []byte, MAXCHAN) protos.AddServer(hostid, forward) log.Printf("game server [id:%v] connected\n", hostid) go _write_routine(output, conn) defer func() { protos.RemoveServer(hostid) core.LogoutServer(hostid) close(forward) close(output) log.Printf("game server [id:%v] disconnected\n", hostid) }() for { select { case msg, ok := <-incoming: // from hub if !ok { return } reader := packet.Reader(msg) protos.HandleRequest(hostid, reader, output) case msg := <-forward: // send forward packet helper.SendChan(0, msg, output) } } }
//---------------------------------------------------------- Event Server start func EventStart() { config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } // start logger if config["event_log"] != "" { cfg.StartLogger(config["event_log"]) } log.Println("Starting Event Server") startup_work() go SignalProc() // Listen service := DEFAULT_SERVICE if config["event_service"] != "" { service = config["event_service"] } log.Println("Event Service:", service) tcpAddr, err := net.ResolveTCPAddr("tcp4", service) checkError(err) listener, err := net.ListenTCP("tcp", tcpAddr) checkError(err) log.Println("Event Server OK.") for { conn, err := listener.AcceptTCP() if err != nil { continue } helper.SetConnParam(conn) go handleClient(conn) } }
//----------------------------------------------- Start Agent when a client is connected func StartAgent(in chan []byte, conn net.Conn) { defer helper.PrintPanicStack() config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } var sess Session sess.IP = net.ParseIP(conn.RemoteAddr().String()) sess.MQ = make(chan IPCObject, DEFAULT_MQ_SIZE) sess.ConnectTime = time.Now() sess.LastPacketTime = time.Now().Unix() sess.KickOut = false // standard 1-sec timer std_timer := make(chan int32, 1) timer.Add(1, time.Now().Unix()+1, std_timer) // write buffer bufctrl := make(chan bool) buf := NewBuffer(&sess, conn, bufctrl) go buf.Start() // max # of operartions allowed before flushing flush_ops, err := strconv.Atoi(config["flush_ops"]) if err != nil { log.Println("cannot parse flush_ops from config", err) flush_ops = DEFAULT_FLUSH_OPS } // cleanup work defer func() { close_work(&sess) close(bufctrl) }() // the main message loop for { select { case msg, ok := <-in: if !ok { return } if result := UserRequestProxy(&sess, msg); result != nil { err := buf.Send(result) if err != nil { return } } sess.LastPacketTime = time.Now().Unix() case msg, ok := <-sess.MQ: // async if !ok { return } if result := IPCRequestProxy(&sess, &msg); result != nil { err := buf.Send(result) if err != nil { return } } case <-std_timer: timer_work(&sess) if session_timeout(&sess) { return } timer.Add(1, time.Now().Unix()+1, std_timer) } // 持久化逻辑#1: 超过一定的操作数量,刷入数据库 if sess.OpCount > flush_ops { _flush(&sess) } // 是否被逻辑踢出 if sess.KickOut { return } } }