0x01 客户端的启动TCP建立连接过程
当客户端启动时会触发TCP connect成功后,服务端触发回调到 LoginServerInitializer.initChannel,在 LoginServerInitializer 所有的 world 和 channel 都为 -1
PacketProcessor.getLoginServerProcessor(); 确定启动TCP回调处理的协议包
在客户端初次连接时,getLoginServerProcessor() 内部确定了当前需要处理哪些客户端发送过来的协议包。具体注册处可以在内部跟踪 registerCommonHandlers, registerLoginHandlers
Client
每一个客户端连接时,服务端会得到客户端的连接IP,并且通过 sessionId.getAndIncrement(); 得到一个唯一ID,将唯一ID,客户端IP和PacketProcessor绑定一起创建一个 Client 客户端信息。
initPipeline 封包加密和解密处理过程初始化
InitializationVector.generateSend()负责出站 和 InitializationVector.generateReceive()负责入站 用来初始化服务端收包和发包的加密向量。new ProtocolFactory 负责加密解密协议编码。
protocolFactory.getProtocol(ServerConstants.VERSION).writeInitialUnencryptedHelloPacket(socketChannel, sendIv, recvIv, client); 负责发送一条未加密的握手包告诉客户端加密参数。GMSV83PacketProtocol.writeInitialUnencryptedHelloPacket.acketCreator.getHello()
setUpHandlers 组装服务端加解密流水线
graph LR
A[客户端发送加密协议] --> B[GMSV83PacketProtocol.decode解码] --> C[Client.channelRead解码后处理协议]
graph LR
A[服务端发送数据包] --> B[GMSV83PacketProtocol.encode加密] --> C[客户端收到加密数据包]
最终过程
客户端启动通过tpc connect与服务端建立连接,服务端连接成功后触发 LoginServerInitializer.initChannel。
回调负责把客户端IP绑定一个唯一ID值,并且创建一个 Client. 将当前 SocketChannel 和 Client 绑定并且设置对数据包入栈和出战的加解密过程 ProtocolFactory。建立成功后,客户端的TCP数据包解密后转发到 Client.channelRead 处理明文协议。
命令封包
| 协议ID | 描述 |
|---|---|
| PONG | 心跳包 |
登录协议封包
| 协议ID | 描述 |
|---|---|
| ACCEPT_TOS | 接受服务条款 |
| AFTER_LOGIN | 登录后操作 |
| SERVERLIST_REREQUEST | 重新请求服务器列表 |
| CHARLIST_REQUEST | 请求角色列表 |
| CHAR_SELECT | 角色选择 |
| LOGIN_PASSWORD | 登录密码 |
| RELOG | 重新登录 |
| SERVERLIST_REQUEST | 请求服务器列表 |
| SERVERSTATUS_REQUEST | 请求服务器状态 |
| CHECK_CHAR_NAME | 检查角色名称 |
| CREATE_CHAR | 创建角色 |
| DELETE_CHAR | 删除角色 |
| VIEW_ALL_CHAR | 查看所有角色 |
| PICK_ALL_CHAR | 选择所有角色 |
| REGISTER_PIN | 注册PIN码 |
| GUEST_LOGIN | 游客登录 |
| REGISTER_PIC | 注册图片 |
| CHAR_SELECT_WITH_PIC | 带图片的角色选择 |
| SET_GENDER | 设置性别 |
| VIEW_ALL_WITH_PIC | 查看所有带图片 |
| VIEW_ALL_PIC_REGISTER | 查看所有注册图片 |