### 消息ID：
#### 1. 规则: 主命令+子命令（高8位+低8位）
| 字段                 | 长度   | 描述                |
|--------------------|------|-------------------|
| `mainCmd`          | 1 字节 | 主命令，范围：0～255      |
| `subCmd`           | 1 字节 | 字命令，范围：0～255      |


#### 2. 示例：
```go
// 编码消息ID:主命令范围 0-255，子命令范围 0-255
func encodeMsgID(mainCmd uint8, subCmd uint8) uint16 {
	return uint16(mainCmd)<<8 | uint16(subCmd)
}

// 解码消息ID
func decodeMsgID(msgID uint16) (uint8, uint8) {
	mainCmd := uint8(msgID >> 8)  // 提取高 8 位
	subCmd := uint8(msgID & 0xFF) // 提取低 8 位
	return mainCmd, subCmd
}
```

### 消息格式：

#### 1. **使用 TCP 协议传输**

| 字段               | 长度   | 描述                                                         |
| ------------------ | ------ | ------------------------------------------------------------ |
| `len`              | 2 字节 | 消息体长度，指示整个消息的长度 (包括 `id` 和 `protobuf message`) |
| `id`               | 2 字节 | 消息的唯一标识符                                             |
| `protobuf message` | N 字节 | 实际的 Protobuf 消息内容                                     |

格式：

```
-------------------------------
| len | id | protobuf message |     
   2     2         N
-------------------------------
```

#### 2. **使用 WebSocket 协议传输**

| 字段               | 长度   | 描述                     |
| ------------------ | ------ | ------------------------ |
| `id`               | 2 字节 | 消息的唯一标识符         |
| `protobuf message` | N 字节 | 实际的 Protobuf 消息内容 |

格式：

```
-------------------------
| id | protobuf message |
   2          N
-------------------------
```

### 默认设置：

- **`lenMsgLen`** 默认为 2 字节。
- **`len` 和 `id`** 在传输过程中使用 **网络字节序**，即大端字节序。

### 编码示例：

假设你有一个 Protobuf 消息，你可以按如下步骤进行编码：

1. **计算消息的长度**：首先计算 Protobuf 消息的实际长度（N 字节）。
2. 生成消息格式:
   - 如果使用 TCP 协议，你需要构造一个长度字段 (`len`)，并将其设置为消息内容的总长度（包括 `id` 和 `protobuf message`）。
   - 如果使用 WebSocket 协议，直接发送 `id` 和 `protobuf message`。

### 代码示例：

假设你使用 Go 语言，下面是一个简化的消息编码示例：

```go
package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
)

func encodeMessage(id uint16, message []byte) ([]byte, error) {
    // 计算消息长度
    lenMsg := uint16(len(message) + 2) // 2 字节的 id

    // 创建 buffer 用于存储最终的编码消息
    var buf bytes.Buffer

    // 将消息长度写入 buffer (2 字节)
    if err := binary.Write(&buf, binary.BigEndian, lenMsg); err != nil {
        return nil, err
    }

    // 将 id 写入 buffer (2 字节)
    if err := binary.Write(&buf, binary.BigEndian, id); err != nil {
        return nil, err
    }

    // 将 protobuf 消息写入 buffer
    buf.Write(message)

    return buf.Bytes(), nil
}

func main() {
    id := uint16(1234) // 消息 ID
    message := []byte("Hello, Protobuf!") // 假设的 Protobuf 消息

    encodedMessage, err := encodeMessage(id, message)
    if err != nil {
        fmt.Println("Error encoding message:", err)
        return
    }

    fmt.Printf("Encoded message: %v\n", encodedMessage)
}

```

### 解码示例：

解码时，你需要提取消息的长度，接着提取 `id` 和 Protobuf 消息内容。确保按照网络字节序来进行处理。

```go
func decodeMessage(encodedMessage []byte) (uint16, []byte, error) {
    // 确保消息长度足够，至少包含 len (2 字节) 和 id (2 字节)
    if len(encodedMessage) < 4 {
        return 0, nil, fmt.Errorf("invalid message")
    }

    // 提取消息长度
    lenMsg := binary.BigEndian.Uint16(encodedMessage[:2])

    // 提取 id
    id := binary.BigEndian.Uint16(encodedMessage[2:4])

    // 提取 protobuf 消息
    message := encodedMessage[4:]

    if len(message) != int(lenMsg)-2 {
        return 0, nil, fmt.Errorf("message length mismatch")
    }

    return id, message, nil
}

```
