下线,下线广播及顶号处理

This commit is contained in:
liuxiaobo 2025-05-27 13:14:01 +08:00
parent a0ee2a3dd3
commit e8e1758d72
5 changed files with 67 additions and 24 deletions

View File

@ -5,7 +5,7 @@ option go_package = "common/proto/ipb";
enum MsgId
{
Unknown = 0;
Internal = -1; // id
Internal = -1; // id
}
@ -26,3 +26,4 @@ message C2SMessage
bytes msg = 4; //
}

View File

@ -8,7 +8,7 @@ enum LoginMsgId
{
Unknown = 0;
C2SUserLogin = 1; //
S2SUserLogin = 2;
S2CUserLogin = 2;
NtfUserOnline = 3;
C2SUserLogout = 4;
S2CUserLogout = 5;
@ -28,7 +28,8 @@ message C2SUserLoginMsg
message S2CUserLoginMsg
{
ErrCode code = 1;
int64 user_id = 2;
int64 user_id = 2;
string token = 3; // token
}
// 线

View File

@ -26,7 +26,7 @@ type LoginMsgId int32
const (
LoginMsgId_Unknown LoginMsgId = 0
LoginMsgId_C2SUserLogin LoginMsgId = 1 // 玩家登陆
LoginMsgId_S2SUserLogin LoginMsgId = 2
LoginMsgId_S2CUserLogin LoginMsgId = 2
LoginMsgId_NtfUserOnline LoginMsgId = 3
LoginMsgId_C2SUserLogout LoginMsgId = 4
LoginMsgId_S2CUserLogout LoginMsgId = 5
@ -38,7 +38,7 @@ var (
LoginMsgId_name = map[int32]string{
0: "Unknown",
1: "C2SUserLogin",
2: "S2SUserLogin",
2: "S2CUserLogin",
3: "NtfUserOnline",
4: "C2SUserLogout",
5: "S2CUserLogout",
@ -47,7 +47,7 @@ var (
LoginMsgId_value = map[string]int32{
"Unknown": 0,
"C2SUserLogin": 1,
"S2SUserLogin": 2,
"S2CUserLogin": 2,
"NtfUserOnline": 3,
"C2SUserLogout": 4,
"S2CUserLogout": 5,
@ -147,6 +147,7 @@ type S2CUserLoginMsg struct {
state protoimpl.MessageState `protogen:"open.v1"`
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` // token
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -195,6 +196,13 @@ func (x *S2CUserLoginMsg) GetUserId() int64 {
return 0
}
func (x *S2CUserLoginMsg) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
// 上线通知
type NtfUserOnlineMsg struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -375,10 +383,11 @@ const file_login_proto_rawDesc = "" +
"\x0fC2SUserLoginMsg\x12\x1a\n" +
"\busername\x18\x01 \x01(\tR\busername\x12\x14\n" +
"\x05token\x18\x02 \x01(\tR\x05token\x12\x18\n" +
"\aversion\x18\x03 \x01(\tR\aversion\"K\n" +
"\aversion\x18\x03 \x01(\tR\aversion\"a\n" +
"\x0fS2CUserLoginMsg\x12\x1f\n" +
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\"+\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" +
"\x05token\x18\x03 \x01(\tR\x05token\"+\n" +
"\x10NtfUserOnlineMsg\x12\x17\n" +
"\auser_id\x18\x02 \x01(\x03R\x06userId\"\x12\n" +
"\x10C2SUserLogoutMsg\"3\n" +
@ -390,7 +399,7 @@ const file_login_proto_rawDesc = "" +
"LoginMsgId\x12\v\n" +
"\aUnknown\x10\x00\x12\x10\n" +
"\fC2SUserLogin\x10\x01\x12\x10\n" +
"\fS2SUserLogin\x10\x02\x12\x11\n" +
"\fS2CUserLogin\x10\x02\x12\x11\n" +
"\rNtfUserOnline\x10\x03\x12\x11\n" +
"\rC2SUserLogout\x10\x04\x12\x11\n" +
"\rS2CUserLogout\x10\x05\x12\x12\n" +

View File

@ -2,20 +2,54 @@ package server
import (
"game/common/proto/pb"
"game/server/gate/model"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
"github.com/fox/fox/ws"
)
/*
gate只处理内部消息(ipb中的消息)避免拦截到外部消息导致不转发给玩家
如果需要gate处理后继续将消息转发给玩家则最后需要调用SendClientData
*/
func (s *GateService) initProcessor() {
s.processor.RegisterMessages(processor.RegisterMetas{
pb.LoginMsgId_NtfUserOnline: {pb.NtfUserOnlineMsg{}, s.onNtfUserOnline},
pb.LoginMsgId_S2CUserLogin: {pb.S2CUserLoginMsg{}, s.onUserLogin},
pb.LoginMsgId_S2CUserLogout: {pb.S2CUserLogoutMsg{}, s.onUserLogout},
})
}
func (s *GateService) onNtfUserOnline(conn ws.IConn, msg *pb.NtfUserOnlineMsg) {
_ = conn
_ = msg
func (s *GateService) onNtfUserOnline(conn ws.IConn, _ *pb.NtfUserOnlineMsg) {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
conn.NotifyClose()
}
// 收到登陆成功消息,判断是否顶号
func (s *GateService) onUserLogin(conn ws.IConn, msg *pb.S2CUserLoginMsg) {
defer func() {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
}()
// 登陆失败,回传玩家
if msg.Code != pb.ErrCode_EC_OK {
return
}
s.wss.SetUserId(conn.Id(), msg.UserId)
ug, _ := model.NewUserGate().Get(conn.UserId(), s.Name())
if ug == nil {
model.NewUserGate().Set(conn.UserId(), s.Name(), msg.Token)
return
}
// 网关不同,说明玩家在其它网关上登陆,
if ug.GateName != s.Name() {
s.SendServiceMsg(service.TopicEx(ug.GateName), conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
}
//conn.NotifyClose()
}
// 收到登出消息
func (s *GateService) onUserLogout(conn ws.IConn, msg *pb.S2CUserLogoutMsg) {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogout), msg)
// 登出的清理工作由WsOnDisconnect实现
conn.NotifyClose()
}

View File

@ -119,13 +119,7 @@ func (s *GateService) OnMessage(data []byte) error {
if req, err := s.processor.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
err = s.processor.Dispatch(iMsg.MsgId, conn, req)
} else {
var cMsg = &pb.ClientMsg{
ServiceId: 0,
MsgId: iMsg.MsgId,
Data: iMsg.Msg,
}
cData, _ := proto.Marshal(cMsg)
_ = conn.SendMsg(cData)
s.SendClientData(conn, iMsg.MsgId, iMsg.Msg)
}
//log.Debug(s.Log("on message:%v", string(msg)))
return nil
@ -200,6 +194,13 @@ func (s *GateService) SendServiceMsg(topic string, conn ws.IConn, msgId int32, m
_ = s.Send(topic, dMsg)
}
// 向玩家发送消息
func (s *GateService) SendClientData(conn ws.IConn, msgId int32, data []byte) {
cMsg := &pb.ClientMsg{MsgId: msgId, Data: data}
dMsg, _ := proto.Marshal(cMsg)
_ = conn.SendMsg(dMsg)
}
// 向玩家发送消息
func (s *GateService) SendClientMsg(conn ws.IConn, msgId int32, msg proto.Message) {
cMsg := &pb.ClientMsg{MsgId: msgId}
@ -208,9 +209,6 @@ func (s *GateService) SendClientMsg(conn ws.IConn, msgId int32, msg proto.Messag
_ = conn.SendMsg(dMsg)
}
/*
todo:针对顶号的情况由其它网关通知本网关向玩家发送下线消息玩家关闭连接后触发WsOnDisconnect此时WsOnDisconnect鉴定时顶号后不需要做任务特殊处理
*/
func (s *GateService) WsOnDisconnect(conn ws.IConn) {
if conn.UserId() > 0 {
userServiceMgr.CleanUser(conn.UserId())
@ -219,7 +217,7 @@ func (s *GateService) WsOnDisconnect(conn ws.IConn) {
log.Error(err.Error())
} else {
// 相同网关则为正常下线删除redis信息然后向内网广播下线
// 不同网关,异地登陆顶号 todo:异地登陆顶号,由其它网关通知本网关向玩家发送下线消息,并主动关闭连接,不广播下线消息,不会触发
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送下线消息(processor中处理),并主动关闭连接,不广播下线消息
if ug.GateName == s.Name() {
model.NewUserGate().Del(conn.UserId(), s.Name())
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.LoginMsgId_NtfUserOffline), &pb.NtfUserOfflineMsg{UserId: conn.UserId()})