Mapz's Blog

可以递归的函数指针

UE5:登录握手控制消息简析

常见控制消息与参数列表

Hello

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Hello, 0, uint8, uint32, FString); // initial client connection message

客户端发起登录初始化

参数:大小端 本地客户端的网络版本 网络加密Token

Upgrade

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Upgrade, 2, uint32); // server tells client their version is incompatible

告诉客户端版本不匹配

参数:服务器版本号

Challenge

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Challenge, 3, FString); // server sends client challenge string to verify integrity

服务器让客户端开始登录

参数:当前时间

Login

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Login, 5, FString, FString, FUniqueNetIdRepl, FString); // client requests to be admitted to the game

客户端发起登录

参数:默认客户端反馈”0” 客户端登录Url字符串 PlayerID 平台名称

Welcome

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Welcome, 1, FString, FString, FString); // server tells client they're ok'ed to load the server's level

服务器欢迎客户端登陆

参数:地图名称 GameMode名称 重定向URL

NetSpeed

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Netspeed, 4, int32); // client sends requested transfer rate

客户端请求设置网速

参数:网速

Failure

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Failure, 6, FString); // indicates connection failure

失败,各种意义上的,一般会断开连接

参数:失败原因

Join

1
DEFINE_CONTROL_CHANNEL_MESSAGE(Join, 9); // final join request (spawns PlayerController)

客户端正式加入游戏中

参数:无

JoinSplit

1
DEFINE_CONTROL_CHANNEL_MESSAGE(JoinSplit, 10, FString, FUniqueNetIdRepl); // child player (splitscreen) join request

向服务器发送分屏玩家加入请求

参数:URL 玩家UniqueNetId

EncryptionAck

1
DEFINE_CONTROL_CHANNEL_MESSAGE(EncryptionAck, 21);

向客户端发送收到流量加密请求

参数:无

GameSpecific

1
DEFINE_CONTROL_CHANNEL_MESSAGE(GameSpecific, 20, uint8, FString); // custom game-specific message routed to UGameInstance for processing

自由定义的命令,会在 UGameInstance::HandleGameNetControlMessage 中处理

参数:命令的Byte 命令的字符串

登录流程控制消息顺序

  • 客户端

    • 发送 Hello 到服务器
  • 服务器收到 Hello

    • 判断两边的网络版本是否匹配,不匹配则发送 Upgrade 到客户端
    • 版本匹配则查看是否有加密 Token
      • 如果没有,则发送 Challenge 到客户端(5.0 以及以前)
      • 如果没有,则判断是否强制开启加密(5.1 以及以后)
        • 如果强制开启加密,则发送 Failure 到客户端,原因是缺少 Encrypt Token
        • 如果没有开启,则发送 Challenge 到客户端
      • 如果有,则调用 UGameInstance::ReceivedNetworkEncryptionToken 解析 Token
        • 如果解析成功
          • 开启加密,向客户端发送 EncryptionAck 到客户端
          • 发送 Challenge 到客户端
        • 解析失败
          • 发送 Failure 到客户端
  • 客户端收到 EncryptionAck

    • 客户端执行 UGameInstance::ReceivedNetworkEncryptionAck ,客户端开启加密
  • 客户端收到 Challenge

    • 组装一些参数(玩家昵称 ,还有 GetGameLoginOptions)到 URL,并和平台名和 PlayerID 等一起发送消息 Login 到服务器
  • 服务器收到 Login

    • 调用 GameMode->PreLogin,使用 Login 消息传入的 PlayerID
      • PreLogin 没有 Error Message
        • 调用 AuthorityGameMode->GameWelcomePlayer
        • 向客户端发送 Welcome
      • PreLogin 有 Error Message,则向客户端发送 Failure
  • 客户端收到 Welcome

    • 发送 NetSpeed 消息到服务器
  • 服务器收到 NetSpeed

    • 设置 Connection 的 NetSpeed
  • 客户端收到 Failure

    • 关闭网络连接
  • 客户端加载地图完成

    • 发送 Join 到服务器
  • 服务器收到 Join

    • 创建 PlayerController
      • 创建失败:发送 Failure
      • 创建成功:标记玩家状态为 Join,开始 ClientTravel