func (self *Manager) handleMsgServerClient(msc *link.Session) { msc.ReadLoop(func(msg link.InBuffer) { glog.Info("msg_server", msc.Conn().RemoteAddr().String(), "say:", string(msg.Get())) self.parseProtocol(msg.Get(), msc) }) }
//其他客户端连接TransferServer处理 func connectTransferServer(session *link.Session, protoMsg systemProto.ProtoMsg) { rev_msg := protoMsg.Body.(*systemProto.System_ConnectTransferServerC2S) serverName := rev_msg.GetServerName() INFO(serverName + " Connect TransferServer") useServerName := strings.Split(serverName, "[")[0] sessions, exists := servers[useServerName] if !exists { sessions = make([]*link.Session, 0, 10) } sessions = append(sessions, session) servers[useServerName] = sessions //GameServer可以有多个 if useServerName == "GameServer" { addr := strings.Split(session.Conn().RemoteAddr().String(), ":") addrIp := addr[0] addrPort, _ := strconv.Atoi(addr[1]) gameConsistent.Add(hashs.NewNode(len(sessions), addrIp, addrPort, serverName, 1)) } send_msg := systemProto.MarshalProtoMsg(&systemProto.System_ConnectTransferServerS2C{}) systemProto.Send(send_msg, session) startDealReceiveMsgC2S(session) }
func newFrontLink(session *link.Session, linkID uint64) *frontendLink { flink := &frontendLink{ session: session, linkId: linkID, clients: make(map[uint64]*link.Session), clientWaits: make(map[uint64]*link.Session), } session.AddCloseCallback(flink, func() { flink.Close() }) go func() { var msg = gatewayMsg{} for { if err := session.Receive(&msg); err != nil { break } switch msg.Command { case CMD_MSG: flink.dispathMsg(msg.ClientId, msg.Data) case CMD_BRD: flink.broadcast(msg.ClientIds, msg.Data) case CMD_NEW_2: flink.newClient(msg.ClientId, msg.ClientIds[0]) case CMD_DEL: flink.delClient(msg.ClientId, false) } } flink.Close() }() return flink }
//登录 func (this UserModule) Login(userName string, session *link.Session) { onlineUser := module.Cache.GetOnlineUserByUserName(userName) if onlineUser != nil { if onlineUser.Session.Id() != session.Id() { //当前在线,但是连接不同,其他客户端连接,需通知当前客户端下线 module.SendOtherLogin(onlineUser.Session) //替换Session module.Cache.RemoveOnlineUser(onlineUser.Session.Id()) //登录成功处理 success := loginSuccess(session, onlineUser.UserName, onlineUser.UserID) if success { module.SendLoginResult(onlineUser.UserID, session) } else { module.SendLoginResult(0, session) } } } else { cacheDbUser := redisProxy.GetDBUserByUserName(userName) if cacheDbUser != nil { this.UserLoginHandle(session, cacheDbUser.Name, cacheDbUser.ID) } else { dbProxy.UserLogin(session.Id(), userName) } } }
func (self *Router) handleMsgServerClient(msc *link.Session) { msc.ReadLoop(func(msg link.InBuffer) { glog.Info("msg_server", msc.Conn().RemoteAddr().String(), " say: ", string(msg.Get())) var c protocol.CmdInternal pp := NewProtoProc(self) err := json.Unmarshal(msg.Get(), &c) if err != nil { glog.Error("error:", err) } switch c.GetCmdName() { case protocol.SEND_MESSAGE_P2P_CMD: err := pp.procSendMsgP2P(c, msc) if err != nil { glog.Warning(err.Error()) } case protocol.CREATE_TOPIC_CMD: err := pp.procCreateTopic(c, msc) if err != nil { glog.Warning(err.Error()) } case protocol.JOIN_TOPIC_CMD: err := pp.procJoinTopic(c, msc) if err != nil { glog.Warning(err.Error()) } case protocol.SEND_MESSAGE_TOPIC_CMD: err := pp.procSendMsgTopic(c, msc) if err != nil { glog.Warning(err.Error()) } } }) }
//LoginServer用户上线 func SetClientSessionOnline(userSession *link.Session) { //发送用户上线消息到serverName protoMsg := &systemProto.System_ClientSessionOnlineC2S{ SessionID: protos.Uint64(userSession.Id()), Network: protos.String(userSession.Conn().RemoteAddr().Network()), Addr: protos.String(userSession.Conn().RemoteAddr().String()), } send_msg := protos.MarshalProtoMsg(protoMsg) sendSystemMsg2("LoginServer", 0, send_msg) }
func sessionReceive(session *link.Session, d dispatch.DispatchInterface) { for { var msg []byte if err := session.Receive(&msg); err != nil { break } d.Process(session, msg) } }
func handleSession(ms *MsgServer, session *link.Session) { session.ReadLoop(func(msg link.InBuffer) { glog.Info(string(msg.Get())) err := ms.parseProtocol(msg.Get(), session) if err != nil { glog.Error(err.Error()) } }) }
func AddSession(session *link.Session) { sessionMutex.Lock() defer sessionMutex.Unlock() sessionNum += 1 sessions[session.Id()] = session session.AddCloseCallback(session, func() { RemoveSession(session) sessionNum -= 1 }) }
//通知GameServer用户登录成功 func SetClientLoginSuccess(userName string, userID uint64, session *link.Session) { send_msg := protos.MarshalProtoMsg(&systemProto.System_ClientLoginSuccessC2S{ UserID: protos.Uint64(userID), UserName: protos.String(userName), SessionID: protos.Uint64(session.Id()), GameServerID: protos.Uint32(0), Network: protos.String(session.Conn().RemoteAddr().Network()), Addr: protos.String(session.Conn().RemoteAddr().String()), }) sendSystemMsgToServer(send_msg) }
func BytesTest(t *testing.T, session *link.Session) { for i := 0; i < 2000; i++ { msg1 := RandBytes(512) err := session.Send(msg1) unitest.NotError(t, err) var msg2 []byte err = session.Receive(&msg2) unitest.NotError(t, err) unitest.Pass(t, bytes.Equal(msg1, msg2)) } }
func ObjectTest(t *testing.T, session *link.Session) { for i := 0; i < 2000; i++ { msg1 := RandObject() err := session.Send(&msg1) unitest.NotError(t, err) var msg2 TestObject err = session.Receive(&msg2) unitest.NotError(t, err) unitest.Pass(t, msg1 == msg2) } }
func StringTest(t *testing.T, session *link.Session) { for i := 0; i < 2000; i++ { msg1 := string(RandBytes(512)) err := session.Send(msg1) unitest.NotError(t, err) var msg2 string err = session.Receive(&msg2) unitest.NotError(t, err) unitest.Pass(t, msg1 == msg2) } }
func (flink *frontendLink) AddClient(session *link.Session) { flink.clientMutex.Lock() defer flink.clientMutex.Unlock() flink.clientWaitId += 1 flink.clientWaits[flink.clientWaitId] = session addr := session.Conn().RemoteAddr() flink.session.Send(&gatewayMsg{ Command: CMD_NEW_1, ClientId: flink.clientWaitId, Data: []byte(addr.Network() + "," + addr.String()), }) }
//登录成功后处理 func (this UserModule) dealLoginSuccess(session *link.Session, userName string, userID uint64) { //通知GameServer登录成功 transferProxy.SetClientLoginSuccess(userName, userID, session) //发送登录成功消息 gameProxy.SendLoginResult(session, userID) //用户下线时处理 session.AddCloseCallback(session, func() { //记录用户下线Log logProxy.UserOffLine(userID) }) //记录用户登录Log logProxy.UserLogin(userID) }
//用户登录成功处理 func (this UserModule) LoginSuccess(session *link.Session, userName string, userID uint64, gameServerID uint32) bool { cacheSuccess := module.Cache.AddOnlineUser(userName, userID, session, gameServerID) if cacheSuccess { session.AddCloseCallback(session, func() { module.Cache.RemoveOnlineUser(session.Id()) DEBUG("用户下线:当前在线人数", module.Cache.GetOnlineUsersNum()) }) DEBUG("用户上线:当前在线人数", module.Cache.GetOnlineUsersNum()) return true } else { ERR("what????", userName) return false } }
func newBackendLink(id uint64, listener *BackendListener, session *link.Session) *backendLink { session.EnableAsyncSend(10000) this := &backendLink{ id: id, listener: listener, session: session, conns: make(map[uint64]*BackendConn), } session.AddCloseCallback(this, func() { this.Close(false) }) go this.loop() return this }
//发送消息到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) } }
//其他客户端连接LogServer处理 func connectLogServer(session *link.Session, protoMsg protos.ProtoMsg) { rev_msg := protoMsg.Body.(*systemProto.System_ConnectLogServerC2S) serverName := rev_msg.GetServerName() servers[serverName] = session session.AddCloseCallback(session, func() { delete(servers, serverName) ERR(serverName + " Disconnect At " + global.ServerName) }) send_msg := protos.MarshalProtoMsg(&systemProto.System_ConnectLogServerS2C{}) protos.Send(session, send_msg) }
///============================ ///消费者 获取图片 func getFile(session *link.Session, req map[string]string) error { seq := req["seq"] //死等 vf := QueueInstance.DeChan() if vf == nil { ULogger.Error("getfile time out,sessioninfo is %s", session.State.(*User).Id) ret := map[string]string{ "action": "res_getfile", "seq": seq, } by, _ := json.Marshal(ret) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) return nil } vf.C = session vf.CInfo = session.State.(*User).Id vf.Status = 2 vf.CGetUnix = time.Now().Unix() ret := map[string]string{ "action": "res_getfile", "seq": seq, "id": vf.Id, "file": vf.File, } by, _ := json.Marshal(ret) VFMapInstance.Update("c_getfile", vf) session.Send(link.Bytes(by)) ULogger.Info("send to client", session.Conn().RemoteAddr().String(), "say:", string(by)) return nil }
func SendGetUserInfoResult(errorCode int32, u *UserModel, session *link.Session) { if errorCode != 0 { SendErrorMsg(errorCode, session) } else { send_msg := MarshalProtoMsg(&GetUserInfoS2C{ UserInfo: &Person{ ID: protos.Uint64(u.DBUser.ID), Name: protos.String(u.DBUser.Name), Money: protos.Int32(u.DBUser.Money), SessionID: protos.Uint64(session.Id()), }, }) Send(send_msg, session) } }
///====================================== ///生产者 ,产生图验图片 func putFile(session *link.Session, req map[string]string) error { file := req["file"] seq := req["seq"] fileid := GetMd5String(file) vf := &VerifyObj{Id: getId(), P: session, C: nil, FileId: fileid, File: file, Status: 1, Result: "0", Seq: seq, PPutUnix: time.Now().Unix()} QueueInstance.Enqueue(vf) VFMapInstance.Put(vf) ULogger.Infof("putfile 进队列 %v\n", vf) //记录p端的操作 if session.State == nil { userId := session.Conn().RemoteAddr().String() user := &User{UserType: "P", Id: userId, WorkTime: time.Now().Format("2006-01-02 15:04:05")} session.State = user Exec(`insert into user_activities(user_id,active_time,active_type,user_type,other_info) values(?,now(),'begin','production',?)`, userId, userId) } return nil }
//获取用户详细信息 func (this UserModule) GetUserInfo(userID uint64, session *link.Session) { onlineUser := module.Cache.GetOnlineUserByUserID(userID) if onlineUser != nil { dbUser := redisProxy.GetDBUser(userID) if dbUser != nil { userModel := NewUserModel(dbUser) module.SendGetUserInfoResult(0, userModel, session) //更新用户最后上线时间,更新内存和数据库 nowTime := time.Now().Unix() redisProxy.UpdateUserLastLoginTime(userID, nowTime) dbProxy.UpdateUserLastLoginTime(session.Id(), userID, nowTime) } else { module.SendGetUserInfoResult(gameProto.User_Not_Exists, nil, session) } } else { module.SendGetUserInfoResult(gameProto.User_Login_Fail, nil, session) } }
//开始处理游戏逻辑消息 func startDealReceiveMsgC2S(session *link.Session) { revMsgChan := make(chan *packet.RAW, 2048) go func() { for { data, ok := <-revMsgChan if !ok { return } dealReceiveMsgC2S(session, *data) } }() for { var msg packet.RAW if err := session.Receive(&msg); err != nil { break } revMsgChan <- &msg } }
//登录 func (this UserModule) Login(userName string, session *link.Session) { onlineUser := module.Cache.GetOnlineUserByUserName(userName) if onlineUser != nil { if onlineUser.Session.Id() != session.Id() { //当前在线,但是连接不同,其他客户端连接,需通知当前客户端下线 gameProxy.SendOtherLogin(onlineUser.Session) //替换Session module.Cache.RemoveOnlineUser(onlineUser.Session.Id()) //登录成功处理 success := this.LoginSuccess(session, onlineUser.UserName, onlineUser.UserID, 0) if success { //登录成功后处理 this.dealLoginSuccess(session, userName, onlineUser.UserID) } else { gameProxy.SendLoginResult(session, 0) } } } else { dbProxy.UserLogin(session.Id(), userName) } }
//添加在线用户缓存 func (this *CacheModule) AddOnlineUser(userName string, userID uint64, session *link.Session) bool { this.onlineUsersMutex.Lock() defer this.onlineUsersMutex.Unlock() //同一账号只能对应一个Session //同一SessionID只能登陆一个账号 _, exists1 := this.onlineUsers[userName] _, exists2 := this.onlineUsersSession[session.Id()] if !exists1 && !exists2 { model := &OnlineUserModel{ Session: session, UserID: userID, UserName: userName, } this.onlineUsers[userName] = model this.onlineUsersID[userID] = userName this.onlineUsersSession[session.Id()] = userName this.onlineUsersNum += 1 return true } else { return false } }
//其他客户端连接TransferServer处理 func connectTransferServer(session *link.Session, protoMsg protos.ProtoMsg) { rev_msg := protoMsg.Body.(*systemProto.System_ConnectTransferServerC2S) serverName := rev_msg.GetServerName() serverID := rev_msg.GetServerID() useServerName := strings.Split(serverName, "[")[0] serverList, exists := servers[useServerName] if !exists { serverList = make([]Server, 0, 10) } server := Server{ session: session, serverID: serverID, serverIndex: len(serverList), } serverList = append(serverList, server) servers[useServerName] = serverList //服务器断开连接处理 session.AddCloseCallback(session, func() { serverList = append(serverList[:server.serverIndex], serverList[server.serverIndex+1:]...) servers[useServerName] = serverList ERR(serverName + " Disconnect At " + global.ServerName) }) //GameServer可以有多个 if useServerName == "GameServer" { addr := strings.Split(session.Conn().RemoteAddr().String(), ":") addrIp := addr[0] addrPort, _ := strconv.Atoi(addr[1]) gameNode := hashs.NewNode(server.serverIndex, addrIp, addrPort, serverName, 1) gameConsistent.Add(gameNode) //GameServer断开连接处理 session.AddCloseCallback(session, func() { //移除此Node gameConsistent.Remove(gameNode) //将此Node的所有用户断开连接 for clientSessionID, gameNodeIndex := range gameUserSessions { if server.serverIndex == gameNodeIndex { clientSession := global.GetSession(clientSessionID) if clientSession != nil { clientSession.Close() } } } }) } //发送连接成功消息 send_msg := protos.MarshalProtoMsg(&systemProto.System_ConnectTransferServerS2C{}) protos.Send(session, send_msg) }
func loginSuccess(session *link.Session, userName string, userID uint64) bool { cacheSuccess := module.Cache.AddOnlineUser(userName, userID, session) if cacheSuccess { session.AddCloseCallback(session, func() { module.Cache.RemoveOnlineUser(session.Id()) DEBUG("下线:在线人数", module.Cache.GetOnlineUsersNum()) }) DEBUG("上线:在线人数", module.Cache.GetOnlineUsersNum()) //通知游戏服务器登录成功 transferProxy.SendClientLoginSuccess(userName, userID, session.Id()) return true } return false }
//发送消息 func Send(msgBody []byte, session *link.Session) { session.Send(packet.RAW(msgBody)) }
func Process(session *link.Session, req map[string]string) error { command, ok := req["action"] if !ok { ULogger.Error("client", session.Conn().RemoteAddr().String(), "bad request ,not found action") session.Close() return nil } if (command == "getfile" || command == "answer") && session.State == nil { ULogger.Error("client", session.Conn().RemoteAddr().String(), "c must login frist") session.Close() return nil } switch command { //p case "putfile": return putFile(session, req) case "reportanswer": return reportAnswer(session, req) //c case "getfile": return getFile(session, req) case "cstart": return cStart(session, req) case "answer": return answer(session, req) default: ULogger.Error("client", session.Conn().RemoteAddr().String(), "not support command") session.Close() //ULogger.Info("sssss") } return nil }