package main import ( "bytes" "common/logger" //pb "common/protocol" pb "WorldTester/pb" "encoding/binary" "errors" "log" "net" "reflect" "time" "github.com/golang/protobuf/proto" ) type MessageHandler func(conn net.Conn, header pb.MessageHeader, msg interface{}) type MessageInfo struct { msgType reflect.Type msgHandler MessageHandler } var ( msg_map = make(map[pb.MSGID]MessageInfo) Max_Message_Size uint16 = 4096 ) func RegisterMessage(msgid pb.MSGID, msg interface{}, handler MessageHandler) { var info MessageInfo info.msgType = reflect.TypeOf(msg.(proto.Message)) info.msgHandler = handler msg_map[msgid] = info } func getTcpClient(uid uint32) net.Conn { conn, err := net.Dial("tcp", server_addr) if err != nil { logger.Info("connect server:%+v error:%=v", server_addr, err.Error()) log.Println("connect server:%+v error:%=v", server_addr, err.Error()) return nil } logger.Info("connect server success! for uid:%+v addr:%v", uid, server_addr) log.Println("connect server success! for uid:%+v addr:%v", uid, server_addr) return conn } /* func clientSendLoop(conn net.Conn) { sms := make([]byte, 128) _ = sms for { fmt.Print("\nenter command:") // _, err := fmt.Scan(&sms) reader := bufio.NewReader(os.Stdin) strBytes, _, err := reader.ReadLine() if err != nil { fmt.Println("invalid input:", err.Error()) break } handleCommand(conn, string(strBytes)) } fmt.Println("send loop exist") } */ func clientRecvLoop(player *PlayerInfo) { tmp := make([]byte, 10240) buf := make([]byte, 0, 10240) var buf_len uint32 defer player.conn.Close() for { player.conn.SetReadDeadline(time.Now().Add(time.Second)) n, err := player.conn.Read(tmp) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { checkPlayer(player) continue } logger.Info("recv conn error:%+v", err) break } buf = append(buf, tmp[:n]...) buf_len += uint32(n) for buf_len >= uint32(Min_Message_Size) { logger.Info("clientRecvLoop receive message") el, err := handleBuffer(player.conn, buf, buf_len) if err != nil { logger.Info("handler buffer error:%+v", err) break } else { buf_len -= el buf = buf[el:] } } checkPlayer(player) } logger.Info("recv loop exist for uid:%v conn:%v", player.uid, player.conn) } func handleBuffer(conn net.Conn, buffer []byte, size uint32) (eat_len uint32, err error) { var header pb.MessageHeader rd := bytes.NewReader(buffer[0:Min_Message_Size]) binary.Read(rd, binary.BigEndian, &header) if header.PackageLen > Max_Message_Size { logger.Info("error got invalid message size:%+v", header.PackageLen) eat_len = size err = nil return } if uint32(header.PackageLen) > size { logger.Info("error message not enough, buffer size:%v, pakcet len:%v header:%+v\n", size, header.PackageLen, header) eat_len = 0 err = errors.New("error not enough") return } dispatchRawData(conn, header, buffer[Min_Message_Size:header.PackageLen]) eat_len = uint32(header.PackageLen) err = nil return } func dispatchRawData(conn net.Conn, header pb.MessageHeader, data []byte) { logger.Info("<-- dispatch new message header:%+v\n", header) msgid := pb.MSGID(header.MsgID) if info, ok := msg_map[msgid]; ok { msg := reflect.New(info.msgType.Elem()).Interface() err := proto.Unmarshal(data, msg.(proto.Message)) if err != nil { return } info.msgHandler(conn, header, msg) return } else { logger.Info("invalid msgid from server:%+v", msgid) } }