置顶 GoWorld客户端服务端通信协议详解(中文版)
发布于 14 天前 作者 xiaonanln 99 次浏览 最后一次编辑是 12 天前 来自 分享

数据包

+----------------+--------------+
| 负载长度 uint32 | 负载 ...byte |
+----------------+--------------+

在GoWorld中,客户端通过TCP/KCP/WebSocket等方式连接服务器。数据按包的格式进行收发。每个包保护一个uint32的负载长度字段和剩余的负载部分。

消息

包的负载部分被解析为消息。每个消息都包含一个uint16的消息类型字段和可能的多个其他字段。消息字段可以有多种不同的类型,如下所示:

  • byte, uint16, uint32, uint64, float32, float64, … : 基本的数据类型,按小字节序(little endian)编码
  • bool: 格式同byte,不过只有1、2两种可能的值
  • Bytes: 一个固定长度的字节数组。读写Bytes类型字段的时候必须提供已知的长度
  • VarBytes: 可变长度的字节数组,相当于一个uint32的字节数组长度加上一个Bytes字段。
  • ClientID: 客户端唯一ID,固定为16字节长度的字符数组,解析为固定长度字符串
  • EntityID: 对象ID(EntityID),固定为16字节长度的字符数组,解析为固定长度字符串
  • VarStr: 和VarBytes类型完全一样,不过字节数组将被解析为字符串
  • Data: 使用VarBytes类型存储使用MessagePack进行编码的二进制数据。这些数据可以使用MessagePack解析。
  • Args: 一般用于收发RPC调用的多个参数。包含一个uint16的参数个数,和多个使用Data类型进行编码的参数。

GoWorld使用完全固定格式的消息结构。一个消息里的多个字段完全按照字节紧挨在一起。打包和解包的代码也需要一一对应,按照消息格式所定义的顺序进行各个字段的读写。以下是客户端、服务端在交互过程中所涉及到的消息类型和结构,我们直接使用Golang代码来说明消息的结构。

在客户端创建对象 (服务端 -> 客户端)

	packet.AppendUint16(MT_CREATE_ENTITY_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendBool(isPlayer)
	packet.AppendEntityID(entityid)
	packet.AppendVarStr(typeName)
	packet.AppendFloat32(x)
	packet.AppendFloat32(y)
	packet.AppendFloat32(z)
	packet.AppendFloat32(yaw)
	packet.AppendData(clientData)

客户端应该在收到这个类型的消息的时候创建客户端对象。客户端可以忽略gidclientid字段。

Destroy Entity (Server -> Client)

	packet.AppendUint16(MT_DESTROY_ENTITY_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendVarStr(typeName)
	packet.AppendEntityID(entityid)

客户端应该在收到这个类型的消息的时候销毁客户端对象。客户端可以忽略gidclientid字段。

RPC between server and client

Call Client Entity Method (Server -> Client)

	packet.AppendUint16(MT_CALL_ENTITY_METHOD_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityID)
	packet.AppendVarStr(method)
	packet.AppendArgs(args)

Client should read entityid, method and args and call the target entity’s method with specified arguments.

Call Server Entity Method (Client -> Server)

	packet.AppendUint16(MT_CALL_ENTITY_METHOD_FROM_CLIENT)
	packet.AppendEntityID(id)
	packet.AppendVarStr(method)
	packet.AppendArgs(args)

Client send messages of this type to call methods of server entities.

Entity Attribute Updates

Notify MapAttr Change By Key (Server -> Client)

	packet.AppendUint16(MT_NOTIFY_MAP_ATTR_CHANGE_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityid)
	packet.AppendData(path)  // path of the map attr
	packet.AppendVarStr(key) // map attr key
	packet.AppendData(val)   // map attr value

Server send messages of this type to clients whenever a MapAttr is modified by some key.

Notify MapAttr Delete By Key (Server -> Client)

	packet.AppendUint16(MT_NOTIFY_MAP_ATTR_DEL_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityid)
	packet.AppendData(path)
	packet.AppendVarStr(key)

Server send messages of this type to clients whenever a MapAttr’s key is deleted.

Notify ListAttr Set by Index (Server -> Client)

	packet.AppendUint16(MT_NOTIFY_LIST_ATTR_CHANGE_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityid)
	packet.AppendData(path)
	packet.AppendUint32(index)
	packet.AppendData(val)

Server send messages of this type to clients whenver a ListAttr is modified by some index.

Notify ListAttr Append (Server -> Client)

	packet.AppendUint16(MT_NOTIFY_LIST_ATTR_APPEND_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityid)
	packet.AppendData(path)
	packet.AppendData(val)

Server send messages of this type to clients whenever a ListAttr appends some value.

Notify ListAttr Pop (Server -> Client)

	packet := gwc.packetConn.NewPacket()
	packet.AppendUint16(MT_NOTIFY_LIST_ATTR_POP_ON_CLIENT)
	packet.AppendUint16(gid)
	packet.AppendClientID(clientid)
	packet.AppendEntityID(entityid)
	packet.AppendData(path)

Server send messages of this type to clients whenever a ListAttr pops some value.

Entity Infos (Position, Yaw) Synchronization

Sync Server Entity Infos (Client -> Server)

	packet.AppendEntityID(entityID)
	packet.AppendFloat32(x)
	packet.AppendFloat32(y)
	packet.AppendFloat32(z)
	packet.AppendFloat32(yaw)

Client send this message to synchronize entity infos to server when entity position or yaw is changed on client.

Sync Client Entity Infos (Server -> Client)

This message consists of a uint16 message type (MT_SYNC_POSITION_YAW_ON_CLIENTS) and N entity infos. Each entity info is 32 bytes which consists of a 16 bytes Entity ID and 4 float32 fields, as shown below.

                // Client message handling code 
		for packet.HasUnreadPayload() {
			entityID := packet.ReadEntityID()
			x := entity.Coord(packet.ReadFloat32())
			y := entity.Coord(packet.ReadFloat32())
			z := entity.Coord(packet.ReadFloat32())
			yaw := entity.Yaw(packet.ReadFloat32())
                        // update client entity position and yaw ...
		}

Client should handle messages of this type to update client entity infos (position and yaw).

回到顶部