// message fetcher func fetcher_task() { //connect to game service clients, err := services.GetAllService(services.SERVICE_GAME) if err != nil { log.Critical(err) os.Exit(-1) } for _, cli := range clients { service, _ := cli.(proto.GameServiceClient) stream, err := service.Notify(context.Background(), &proto.Game_Nil{}) if err != nil { log.Critical(err) os.Exit(-1) } go func() { for { p, err := stream.Recv() if err == io.EOF { log.Infof("stream recv EOF err :%v", err) return } if err != nil { log.Critical("stream recv gs err", err) continue } registry.Deliver(p.Uid, p.Content) } }() } }
func (f *forwarder) recv(key string, cli GameService_PacketClient) { for { in, err := cli.Recv() if err == io.EOF { log.Infof("stream recv EOF err : %v", err) return } if err != nil { log.Critical("Failed to receive a note : %v", err) continue } registry.Deliver(in.Uid, in.Content) } }
// start a goroutine when a new connection is accepted func handleClient(conn *net.TCPConn) { defer utils.PrintPanicStack() // set per-connection socket buffer conn.SetReadBuffer(SO_RCVBUF) // set initial socket buffer conn.SetWriteBuffer(SO_SNDBUF) // initial network control struct header := make([]byte, 2) in := make(chan []byte) defer func() { close(in) // session will close }() // create a new session object for the connection var sess Session host, port, err := net.SplitHostPort(conn.RemoteAddr().String()) if err != nil { log.Error("cannot get remote address:", err) return } sess.IP = net.ParseIP(host) log.Infof("new connection from:%v port:%v", host, port) // session die signal sess_die := make(chan bool) // create a write buffer out := new_buffer(conn, sess_die) go out.start() // start one agent for handling packet wg.Add(1) go agent(&sess, in, out, sess_die) // network loop for { // solve dead link problem conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second)) n, err := io.ReadFull(conn, header) if err != nil { log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n) return } size := binary.BigEndian.Uint16(header) // alloc a byte slice for reading payload := make([]byte, size) // read msg n, err = io.ReadFull(conn, payload) if err != nil { log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n) return } select { case in <- payload: // payload queued case <-sess_die: log.Warningf("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP) return } } }