# ServerModule

**区服进程**：同时提供

- **客户端游戏 TCP**（`game.client-tcp.port`，默认示例 **9091**）：`CommandSource.Client_TCP`
- **连跨服的出站 TCP 长连接**（`cross.host` / `cross.port`，示例 **9200**）：由 **`CrossTcpClient`** 维护，`ProtoRegistry` 中对应逻辑仍按跨服协议，但 **连接发起在区服**
- **HTTP**（`server.port`，默认 **8080**）：Demo API、探针、静态探测页

## 总体数据流

```mermaid
flowchart TB
  subgraph External["外部"]
    GAME[游戏客户端 TCP]
    BROWSER[浏览器 / HTTP 客户端]
  end
  subgraph Server["ServerModule"]
    CTS[ClientTcpServer :9091]
    HTTP[HTTP :8080]
    REG[ServerCommandRegistry]
    C2[TcpPath2 等命令]
    CC[CrossTcpClient 长连接]
  end
  subgraph Cross["CrossModule :9200"]
    XT[Cross TCP]
  end
  GAME --> CTS --> REG --> C2
  BROWSER --> HTTP
  C2 --> CC --> XT
```

## 1. 客户端 TCP（主入口）

- **`ClientTcpServer`**：`ApplicationReadyEvent` 后绑定端口（`@Order` 较早，保证先于跨服预热）。
- **`ClientTcpChannelInitializer`**：解码器 + **`CmdRpcTcpFrameHandler`**（`linkSource = Client_TCP`，注入 **`ServerCommandRegistry`** 与 **`CrossTcpClient`** 作为 **`CrossRpcInvoker`**）。

```mermaid
sequenceDiagram
  participant C as 客户端
  participant S as ClientTcpServer
  participant R as ServerCommandRegistry
  participant Cmd as GameCommand
  participant X as CrossTcpClient
  C->>S: 帧: CmdRpcEnvelope
  S->>R: resolve(service, method)
  R->>Cmd: execute
  opt 路径2/3
    Cmd->>X: roundTrip(跨服信封)
    X-->>Cmd: 跨服响应
  end
  Cmd-->>S: 响应 CmdRpcEnvelope
  S-->>C: 帧
```

### 三条路径（概念对照）

| 路径 | Client TCP service/method | 是否调跨服 | 说明 |
|------|---------------------------|------------|------|
| 1 | Service_1 / Method1 | 否 | Echo |
| 2 | Service_2 / Method2 | 是 | `CrossProxy*` → 转 `CrossForward*` → 跨服 → 回写 `CrossProxyStc`（含 `server_note`） |
| 3 | Service_3 / Method3 | 是 | 信封对客户端为 S3，payload 为 `CrossForwardCts`；区服只转发跨服 |

实现类：`TcpPath1LocalEchoCommand`、`TcpPath2CrossThenServerCommand`、`TcpPath3CrossRelayCommand`。

## 2. 区服 → 跨服：`CrossTcpClient`

- **单连接长连**：`ensureConnected()` 建链；断线后 `linkRegistered=false`，下次业务或心跳会重建。
- **注册**：`Service_4` + `Register`，载荷 `CrossLinkRegisterCts`（`cross.server-id`、`cross.token`）。
- **心跳**：`CrossTcpHeartbeatTask` 按 `cross.heartbeat-interval-ms`（默认 15000）调用 `sendHeartbeat()`（`Service_4` + `Heartbeat`）。
- **多路复用**：每次 `roundTrip` 分配 **`link_seq`**，在 `pendingBySeq` 中挂 `CompletableFuture`；入站 **`dispatchInbound`** 按 `link_seq` 完成 Future。

```mermaid
stateDiagram-v2
  [*] --> Disconnected
  Disconnected --> Connected: ensureConnected
  Connected --> Registered: Service_4 Register OK
  Registered --> Registered: roundTrip / Heartbeat
  Registered --> Disconnected: 断链 / 心跳失败
```

- **预热**：`CrossTcpClient.warmupCrossLink()` 监听 `ApplicationReadyEvent`（`@Order` 较低，在 **`ClientTcpServer` 绑定之后**），提前建链+注册。

配置示例见根目录 `README.md` 或本模块 `application.yml`：

- `cross.host`、`cross.port`（须与 CrossModule `cross.tcp.port` 一致）
- `cross.server-id`、`cross.token`、`cross.heartbeat-interval-ms`

## 3. HTTP

- **`/api/ping`**（`PingController`）：探活。
- **`/api/config/client-tcp`**（`ClientTcpConfigController`）：返回 `game.client-tcp.port`。
- **`/api/demo/*`**：Mongo / Redis / 事件 / 模块 tick 等演示接口（见 `DemoApiController`）。

## 4. 其它 Demo（非网络核心）

- MongoDB / Redis / 事件 / 玩家模块 tick 等：见 `com.huangzj.server` 下 `web`、`mongo`、`redis`、`module` 等包。

## 5. 本机命令行压测三条 TCP 路径

`com.huangzj.server.demo.TcpPathsDemo`：与客户端相同帧格式，默认 `127.0.0.1:9091`。

```bash
java -cp ... com.huangzj.server.demo.TcpPathsDemo [host] [port]
```

## 6. 日志

- `app.logging.dir`：默认 `logs/ServerModule`
- `logback-spring.xml`：`info.log`（INFO+WARN，不含 ERROR）与 `error.log`（仅 ERROR）

## 7. 启动顺序建议

1. 启动 **CrossModule**（端口 9200）。  
2. 启动 **ServerModule**（HTTP 8080，客户端 TCP 9091）。  
3. 用 `TcpPathsDemo` 或自建 TCP 客户端按路径 2 组帧，可验证经区服到跨服的全链路。
