网络消息的定义

注意,ET 8.0仍然是通过proto定义消息的,但是会通过工具转为cs,最后序列化/反序列化的时候使用的是memory pack

协议定义在Config/Proto目录

// ResponseType NetClient2Main_Login
message Main2NetClient_Login // IRequest
{
	int32 RpcId = 1;
	int32 OwnerFiberId = 2;
	string Account = 3;		// 账号
	string Password = 4; 	// 密码
}

message NetClient2Main_Login // IResponse
{
	int32 RpcId = 1;
	int32 Error = 2;
	string Message = 3;

	int64 PlayerId = 4;
}

这只是作为一个例子,具体的含义以后再说

服务器连接流程

ET管理的核心之一就是Scene,我们可以找到一个枚举,定义了所有Scene的类型

[Flags]
public enum SceneType: long
{
    None = 0,
    Main = 1, // 主纤程,一个进程一个, 初始化从这里开始
    NetInner = 1 << 2, // 负责进程间消息通信
    Realm = 1 << 3,
    Gate = 1 << 4,
    Http = 1 << 5,
    Location = 1 << 6,
    Map = 1 << 7,
    Router = 1 << 8,
    RouterManager = 1 << 9,
    Robot = 1 << 10,
    BenchmarkClient = 1 << 11,
    BenchmarkServer = 1 << 12,
    Match = 1 << 14,
    Room = 1 << 15,
    LockStepClient = 1 << 16,
    LockStepServer = 1 << 17,
    RoomRoot = 1 << 18,
    Watcher = 1 << 19,

    // 客户端
    Demo = 1 << 30,
    Current = 1L << 31,
    LockStep = 1L << 32,
    LockStepView = 1L << 33,
    DemoView = 1L << 34,
    NetClient = 1L << 35,

    All = long.MaxValue,
}

这些类型和启服流程是息息相关的

配置定义 Config\Excel\StartConfig\Localhost

打开StartSceneConfig.xlsx,这里面是所有运行入口会创建的Scene,一共十二个,也就是服务器一启动就会创建12个Fiber

image-20240502154142276

image-20240502154150056

获取软路由地址

image-20240502154645585

如前面所说,客户端一般有两个Fiber,业务层Fiber发起登录请求,先转发给客户端本地网络层,此时网络层向RouterManager进行一次HTTP请求,获取到所有软路由的地址,也就是配置表中的四个

客户端与服务端所有的消息通信,都必须通过软路由转发

请求登录令牌

image-20240502160327243

获取到软路由地址之后,客户端向Realm服请求分配网关,并由Realm服向网关服请求一个网关令牌,最后返回给客户端

最后客户端持有令牌,直接连接对应的网关,此时会创建对应的playerId映射

Map服

image-20240502160603951

虽然名字叫做Map服,但其实不是地图服务器,叫做GameLogic服更加恰当,Gate所创建的Unit,可以说是每一个客户端在服务器上的映射,每一个客户端处理Unit都会被放到某一个Map服上,网关服可以通过Location服务器定位客户端对应的Unit,也可以说,每一个Unit都对应一个玩家

Actor模型与Fiber通讯

对于ET而言,只要挂载了MailBoxComponent的Entity,那都可以认为是一个Actor,而这个Actor上的任何东西你都可以当做是一个Unit,只要你想

比如说我们的登录组件,他就可以是一个Unit,我们通过这个组件可以进行登录消息的收发

image-20240502161202890

同一个进程的Fiber进行交互,这里的ProcessInnerSender只是一个消息队列

image-20240507140346910

不同进程之间的Fiber进行交互,每个进程都会内涵一个InnerFiber,该进程内的所有Fiber先通过消息队列和InnerFiber交互,InnerFiber再和其他进行的InnerFiber交互

image-20240502161651460

不同Fiber之间的Unit如何确定位置呢?比如Fiber1的Unit1想给Fiber2的Unit6发送消息。

image-20240502161850294

每一个unit都关联了一个结构体ActorId,这个结构体可以定位Unit的位置信息

public partial struct ActorId
{
    public Address Address;
    // 实例ID,一般是Entity的,每一个Entity都不同
    public long InstanceId;
}
public partial struct Address
{
    // 这个似乎默认是1
    public int Process;
	// 纤程ID
    public int Fiber;
}

基本上就是FiberID+InstanceID可以锁定唯一的Unit