109 lines
4.2 KiB
Markdown
109 lines
4.2 KiB
Markdown
# 断开连接
|
||
|
||
> 用户流程:主动断开 / 网络异常断开 / 被踢出 → 清理会话 → 返回主页
|
||
> 对应程序流程:TsClient.disconnect() 或 onDisconnected(error) 或 onKicked(reason) → 停止写操作 → 清理会话状态
|
||
|
||
---
|
||
|
||
## 一、状态树
|
||
|
||
### Client 总状态树(断开相关部分)
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
ROOT[Client 生命周期状态树<br/>断开相关部分]
|
||
|
||
ROOT --> D[断开过程 Disconnecting<br/>正在主动或被动结束会话]
|
||
ROOT --> X[已结束 Terminated<br/>当前会话资源已清理]
|
||
|
||
D --> D1[GracefulDisconnect<br/>用户调用 TsClient.disconnect 优雅退出]
|
||
D --> D2[UnexpectedDisconnect<br/>网络或服务端导致 onDisconnected]
|
||
D --> D3[Kicked<br/>onKicked 表示自己被踢]
|
||
|
||
X --> X1[清理命令请求<br/>取消未完成的业务操作]
|
||
X --> X2[清理语音与传输<br/>停止语音和文件连接]
|
||
X --> X3[清理会话状态<br/>移除频道成员等临时事实]
|
||
```
|
||
|
||
---
|
||
|
||
## 二、时序:主动断开、异常断开与被踢
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant UI as 上层应用<br/>展示连接状态并触发退出
|
||
participant VM as ViewModel<br/>收集 EventBus 事件
|
||
participant BRIDGE as TSBridge<br/>管理连接生命周期
|
||
participant SDK as Go SDK (gomobile)<br/>管理连接与断开事件
|
||
participant TS as TeamSpeak 服务器<br/>关闭或终止客户端会话
|
||
participant STORE as 会话数据仓库<br/>保存当前连接的临时事实
|
||
|
||
alt 用户主动断开
|
||
UI->>VM: DisconnectRequested
|
||
VM->>VM: 状态改为 disconnecting
|
||
VM->>BRIDGE: TSBridge.disconnect()
|
||
BRIDGE->>SDK: gomobile Disconnect
|
||
SDK->>TS: shutdown reason
|
||
TS-->>SDK: 连接关闭
|
||
SDK-->>BRIDGE: OnDisconnected 回调
|
||
BRIDGE->>BRIDGE: EventBus.emit(Disconnected)
|
||
BRIDGE->>VM: EventBus 分发 Disconnected 事件
|
||
else 网络或服务器异常
|
||
TS--xSDK: UDP 会话中断
|
||
SDK-->>BRIDGE: OnDisconnected 回调
|
||
BRIDGE->>BRIDGE: EventBus.emit(Disconnected)
|
||
BRIDGE->>VM: EventBus 分发 Disconnected 事件
|
||
else 自己被踢
|
||
TS-->>SDK: notifyclientleftview reasonid=4/5
|
||
SDK-->>BRIDGE: OnKicked 回调
|
||
BRIDGE->>BRIDGE: EventBus.emit(Kicked)
|
||
BRIDGE->>VM: EventBus 分发 Kicked 事件
|
||
end
|
||
|
||
VM->>VM: 停止语音与文件传输
|
||
VM->>STORE: 清理频道、成员和 Pending
|
||
STORE-->>UI: 返回已断开或失败页面
|
||
```
|
||
|
||
---
|
||
|
||
## 三、事件依赖
|
||
|
||
### 断开相关前置依赖矩阵
|
||
|
||
| 操作或事件 | 必须依赖 | 建议依赖 | 依赖失败时的处理 |
|
||
| --- | --- | --- | --- |
|
||
| `Disconnected` 事件 | 已注册 EventBus 事件收集 | 保存断开原因 | 停止全部依赖连接的操作 |
|
||
| `Kicked` 事件 | 已注册 EventBus 事件收集 | 区分 reasonid 4 和 5 | 清理会话且不伪装为普通成员离开 |
|
||
|
||
### 事件依赖图(断开阶段)
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
DISCONNECTED[EventBus Disconnected 事件<br/>接收连接终止事件] --> STOP[停止依赖操作<br/>禁止命令、语音和新文件传输]
|
||
KICKED[EventBus Kicked 事件<br/>接收自己被踢事件] --> STOP
|
||
STOP --> CLEAN[清理会话状态<br/>移除当前连接的实体与 Pending]
|
||
```
|
||
|
||
### 服务端通知映射
|
||
|
||
| 服务端通知 | TSBridge 回调 → EventBus 事件 | 上层状态依赖 | 中文说明 |
|
||
| --- | --- | --- | --- |
|
||
| `notifyclientleftview`,`reasonid=4/5` 且为自己 | `OnKicked` → `Kicked` | 当前会话、语音、导航 | SDK 将自己被踢转换为独立事件 |
|
||
|
||
### 生命周期约束(断开相关)
|
||
|
||
- `TSBridge.disconnect()` 用于主动优雅退出;`Disconnected` 事件用于观察最终断开结果或异常断开。
|
||
- `Kicked` 事件来源于 `notifyclientleftview` 的特定原因,必须与普通成员离开区分。
|
||
- 断开后应停止语音、拒绝新命令,并清理只属于当前会话的状态。
|
||
|
||
### 权威性划分
|
||
|
||
| 数据 | 推荐权威来源 | 原因 |
|
||
| --- | --- | --- |
|
||
| 被踢状态 | EventBus `Kicked` 事件 | SDK 已从离开事件原因中识别自己被踢 |
|
||
|
||
### 统一实现原则(断开相关)
|
||
|
||
- **断开时统一清理当前会话资源。** 防止旧成员、频道和 Pending 污染下一次连接。
|