//反序列化 func UnmarshalProtoMsg(msg []byte) ProtoMsg { if len(msg) < 2 { return NullProtoMsg } msgID := binary.GetUint16LE(msg[:2]) if !IsValidID(msgID) { return NullProtoMsg } msgBody := protos.GetMsgObject(msgID) if msgBody == nil { return NullProtoMsg } err := proto.Unmarshal(msg[2:], msgBody) if err != nil { return NullProtoMsg } return ProtoMsg{ ID: msgID, Body: msgBody, } }
//反序列化消息 func UnmarshalProtoMsg(msg []byte) ProtoMsg { if len(msg) < 10 { return NullProtoMsg } msgID := binary.GetUint16LE(msg[:2]) if !IsValidID(msgID) { return NullProtoMsg } identification := binary.GetUint64LE(msg[2:10]) msgBody := protos.GetMsgObject(msgID) if msgBody == nil { return NullProtoMsg } err := proto.Unmarshal(msg[10:], msgBody) if err != nil { return NullProtoMsg } return ProtoMsg{ ID: msgID, Body: msgBody, Identification: identification, } }
//将消息写入Chan func (c *DummyConn) PutMsg(msg []byte) { msgLen := len(msg) - 8 msgID := binary.GetUint16LE(msg[:2]) msgBody := msg[10:] saveMsg := make([]byte, msgLen) binary.PutUint16LE(saveMsg[:2], msgID) copy(saveMsg[2:], msgBody) c.recvChan <- saveMsg }
//发送消息到TransferServer, 网关调用 func SendToGameServer(userSession *link.Session, msg []byte) { send_msg := make([]byte, 8+len(msg)) copy(send_msg[:2], msg[:2]) binary.PutUint64LE(send_msg[2:10], userSession.Id()) copy(send_msg[10:], msg[2:]) //C2S消息,发送到GameServer或者LoginServer msgID := binary.GetUint16LE(send_msg[:2]) if gameProto.IsValidLoginID(msgID) { sendGameMsg("LoginServer", send_msg) } else { sendGameMsg("GameServer", send_msg) } }
//初始化 func InitServer(port string) error { servers = make(map[string]*link.Session) asyncMsgs = list.New() db.Init() startSysDB() createRevGoroutines() listener, err := link.Serve("tcp", "0.0.0.0:"+port, packet.New( binary.SplitByUint32BE, 1024, 1024, 1024, )) if err != nil { return err } listener.Serve(func(session *link.Session) { for { var msg packet.RAW if err := session.Receive(&msg); err != nil { break } msgID := binary.GetUint16LE(msg[:2]) if systemProto.IsValidID(msgID) { //系统消息 dealReceiveSystemMsgC2S(session, msg) } else if dbProto.IsValidAsyncID(msgID) { //异步DB消息 asyncMsgs.PushBack(msg) } else { //同步DB消息 useObj := revSyncMsgGoroutines[revSyncMsgGoroutineIndex] useObj.revMsgChan <- goroutineMsg{msg, session} revSyncMsgGoroutineIndex++ if revSyncMsgGoroutineIndex == revSyncMsgGoroutineNum { revSyncMsgGoroutineIndex = 0 } } } }) return nil }
//发送消息到用户客户端 func sendToGateServer(msg []byte) { if len(msg) < 10 { return } msgID := binary.GetUint16LE(msg[:2]) msgIdentification := binary.GetUint64LE(msg[2:10]) msgBody := msg[10:] userSession := global.GetSession(msgIdentification) if userSession == nil { return } result := make([]byte, len(msg)-8) binary.PutUint16LE(result[:2], msgID) copy(result[2:], msgBody) userSession.Send(result) }
func (this Handle) DealMsg(session *link.Session, msg []byte) { msgID := binary.GetUint16LE(msg[:2]) var protoMsg protos.ProtoMsg if systemProto.IsValidID(msgID) || logProto.IsValidID(msgID) || gameProto.IsValidID(msgID) { protoMsg = protos.UnmarshalProtoMsg(msg) } else if dbProto.IsValidID(msgID) { protoMsg = dbProto.UnmarshalProtoMsg(msg) } if protoMsg == protos.NullProtoMsg { ERR("收到Proto未处理消息:", msgID) return } if f, exists := this[msgID]; exists { f(session, protoMsg) } else { ERR("收到Handle未处理消息:", msgID) } }
//处理接收到的消息 func dealReceiveMsgC2S(session *link.Session, msg packet.RAW) { if len(msg) < 2 { return } msgID := binary.GetUint16LE(msg[:2]) if systemProto.IsValidID(msgID) { dealReceiveSystemMsgC2S(session, msg) } else if gameProto.IsValidID(msgID) { if msgID%2 == 1 { //C2S消息,发送到GameServer或者LoginServer if gameProto.IsValidLoginID(msgID) { sendGameMsg("LoginServer", msg) } else { sendGameMsg("GameServer", msg) } } else { //S2C消息,发送到GateServer sendGameMsg("GateServer", msg) } } }
func (c *TransferProxyConn) Receive(msg interface{}) error { data, ok := <-c.recvChan if !ok { return io.EOF } msgID := binary.GetUint16LE(data[:2]) msgBody := data[10:] result := make([]byte, len(data)-8) binary.PutUint16LE(result[:2], msgID) copy(result[2:], msgBody) if fast, ok := msg.(packet.FastInMessage); ok { return fast.Unmarshal( &io.LimitedReader{bytes.NewReader(result), int64(len(result))}, ) } msg.(packet.InMessage).Unmarshal(result) return nil }
func (this HandleFuncCondition) DealMsg(session *link.Session, msg []byte) { msgID := binary.GetUint16LE(msg[:2]) if this.Condition(msgID) { this.H(session, msg) } }
func Test_gateway(t *testing.T) { DEBUG("消息通信测试") var wg sync.WaitGroup var successNum uint32 for i := 0; i < 3000; i++ { wg.Add(1) go func(flag int) { // if flag != 0 && RandomInt31n(100) < 50 { // flag -= 1 // } defer wg.Done() var count uint32 = 0 var userName string = "User" + strconv.Itoa(flag) //超时处理 timerFunc := func() { ERR("失败:", userName, count) } var timer *time.Timer = time.AfterFunc(10*time.Second, timerFunc) //连接服务器 client, err := link.ConnectTimeout("tcp", "0.0.0.0:"+cfg.GetValue("gateway_port"), time.Second*3, protocol) if !unitest.NotError(t, err) { return } defer client.Close() count += 1 //接收服务器连接成功消息 var revMsg packet.RAW // err = client.Receive(&revMsg) // if !unitest.NotError(t, err) { // return // } // msg := &gameProto.ConnectSuccessS2C{} // proto.Unmarshal(revMsg[2:], msg) // DEBUG(binary.GetUint16LE(revMsg[:2]), msg) count += 1 //发送登录消息 send_msg := createLoginBytes(userName) // DEBUG("发送数据:", flag, send_msg) err = client.Send(send_msg) if !unitest.NotError(t, err) { return } count += 1 //接受登录成功消息 err = client.Receive(&revMsg) if !unitest.NotError(t, err) { return } // DEBUG(binary.GetUint16LE(revMsg[:2])) msg1 := &gameProto.UserLoginS2C{} proto.Unmarshal(revMsg[2:], msg1) count += 1 if !unitest.Pass(t, msg1.GetUserID() > 0) { return } count += 1 //发送获取用户信息消息 if msg1.GetUserID() != 0 { err = client.Send(createGetUserInfoBytes(msg1.GetUserID())) if !unitest.NotError(t, err) { return } count += 1 //接受用户信息消息 err = client.Receive(&revMsg) if !unitest.NotError(t, err) { return } count += 1 if binary.GetUint16LE(revMsg[:2]) == gameProto.ID_ErrorMsgS2C { msg2 := &gameProto.ErrorMsgS2C{} proto.Unmarshal(revMsg[2:], msg2) // DEBUG(binary.GetUint16LE(revMsg[:2]), msg2) } else { msg2 := &gameProto.GetUserInfoS2C{} proto.Unmarshal(revMsg[2:], msg2) // DEBUG(binary.GetUint16LE(revMsg[:2]), msg2) successNum += 1 DEBUG("成功:", userName, msg1.GetUserID(), successNum) } } timer.Stop() }(i) } wg.Wait() }