# 频道连接状态管理 (/zh-CN/realtime-media/rtc/build/initialize-and-channel/channel-connection)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理]

### 连接状态 [#连接状态]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `onConnectionStateChanged(CONNECTING, CONNECTING)` 回调。 成功加入频道后，UID1 收到 `onConnectionStateChanged(CONNECTED, JOIN_SUCCESS)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(FAILED, JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，将以下代码复制到 `IRtcEngineEventHandler` 初始化过程中。

```java
public void onConnectionStateChanged(int state, int reason) {
    super.onConnectionStateChanged(state, reason);
    Log.i(TAG, "onConnectoionStateChanged->" + ", state->" + state + ", reason->" + reason);
}
```

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息]

### 连接状态 [#连接状态-1]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-android-markdown-0-1-1 details](#table-slot-channel-connection-android-markdown-0-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。 此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-android-markdown-0-4-1 details](#table-slot-channel-connection-android-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-android-markdown-0-1-1"></a>

**channel-connection-android-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-android-markdown-0-4-1"></a>

**channel-connection-android-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(Reconnecting, Lost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-android-markdown-1-1-1 details](#table-slot-channel-connection-android-markdown-1-1-1) |
| Connecting | [channel-connection-android-markdown-1-2-1 details](#table-slot-channel-connection-android-markdown-1-2-1) |
| Connected | [channel-connection-android-markdown-1-3-1 details](#table-slot-channel-connection-android-markdown-1-3-1) |
| Reconnecting | [channel-connection-android-markdown-1-4-1 details](#table-slot-channel-connection-android-markdown-1-4-1) |
| Failed | [channel-connection-android-markdown-1-5-1 details](#table-slot-channel-connection-android-markdown-1-5-1) |

<a id="table-slot-channel-connection-android-markdown-1-1-1"></a>

**channel-connection-android-markdown-1-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-android-markdown-1-2-1"></a>

**channel-connection-android-markdown-1-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-android-markdown-1-3-1"></a>

**channel-connection-android-markdown-1-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-android-markdown-1-4-1"></a>

**channel-connection-android-markdown-1-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-android-markdown-1-5-1"></a>

**channel-connection-android-markdown-1-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考]

- [`getConnectionState`](/zh-CN/api-reference/rtc/android/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/android/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-1]

### 连接状态 [#连接状态-2]

当连接状态发生变化时，声网会发送 `connectionChangedToState` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-1]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-oc.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannelByToken` 请求。
- T1：调用 `joinChannelByToken` 200 ms 后，UID1 加入频道。同时，UID1 收到 `connectionChangedToState(Connecting, Connecting)` 回调。成功加入频道后，UID1 收到 `connectionChangedToState(Connected, JoinSuccess)` 和 `didJoinChannel` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `didJoinedOfUid` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `rtcEngineConnectionDidLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `didOfflineOfUid` 回调。
- T7：如果 UID 1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `connectionChangedToState(Failed, JoinFailed)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-1]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-1]

本节介绍如何使用 `connectionChangedToState` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `AgoraRtcEngineDelegate` 的文件，将以下代码复制到 `AgoraRtcEngineDelegate` 初始化过程中。

```swift
func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionState, reason: AgoraConnectionChangedReason) {
    LogUtils.log(message: "Connection state changed: \(state) \(reason)", level: .info)
}
```

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`connectionChangedToState` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-1]

### 连接状态 [#连接状态-3]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-ios-macos-markdown-0-1-1 details](#table-slot-channel-connection-ios-macos-markdown-0-1-1) |
| Connecting | 调用 `didJoinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `didJoinChannel` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-ios-macos-markdown-0-4-1 details](#table-slot-channel-connection-ios-macos-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannelByToken` 再次加入频道。 |

<a id="table-slot-channel-connection-ios-macos-markdown-0-1-1"></a>

**channel-connection-ios-macos-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannelByToken` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-ios-macos-markdown-0-4-1"></a>

**channel-connection-ios-macos-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `didRejoinChannel` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `connectionChangedToState(Reconnecting, Lost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-1]

`connectionChangedToState` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-ios-macos-markdown-1-1-1 details](#table-slot-channel-connection-ios-macos-markdown-1-1-1) |
| Connecting | [channel-connection-ios-macos-markdown-1-2-1 details](#table-slot-channel-connection-ios-macos-markdown-1-2-1) |
| Connected | [channel-connection-ios-macos-markdown-1-3-1 details](#table-slot-channel-connection-ios-macos-markdown-1-3-1) |
| Reconnecting | [channel-connection-ios-macos-markdown-1-4-1 details](#table-slot-channel-connection-ios-macos-markdown-1-4-1) |
| Failed | [channel-connection-ios-macos-markdown-1-5-1 details](#table-slot-channel-connection-ios-macos-markdown-1-5-1) |

<a id="table-slot-channel-connection-ios-macos-markdown-1-1-1"></a>

**channel-connection-ios-macos-markdown-1-1-1 details**

- `LeaveChannel`(5)：用户离开频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-2-1"></a>

**channel-connection-ios-macos-markdown-1-2-1 details**

- `Connecting`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-3-1"></a>

**channel-connection-ios-macos-markdown-1-3-1 details**

- `JoinSuccess`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-4-1"></a>

**channel-connection-ios-macos-markdown-1-4-1 details**

- `Interrupted`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `Lost`(16)：SDK 和服务器失去连接。
- `SettingProxyServer`(11)：由于设置了代理服务器，SDK 尝试重连。
- `ClientIpAddressChanged`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KeepAliveTimeout`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RenewToken`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-ios-macos-markdown-1-5-1"></a>

**channel-connection-ios-macos-markdown-1-5-1 details**

- `BannedByServer`(3)：用户被服务器禁止。
- `JoinFailed`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannelByToken` 重新加入频道。
- `InvalidAppId`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `InvalidChannelName`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。
- `TokenExpired`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用  `joinChannelByToken` 加入频道。
- `RejectedByServer`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 调用 `joinChannelByToken`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-1]

- [`getConnectionState`](/zh-CN/api-reference/rtc/ios/network#api_irtcengine_getconnectionstate)
- [`connectionChangedToState`](/zh-CN/api-reference/rtc/ios/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="macos" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-2]

### 连接状态 [#连接状态-4]

当连接状态发生变化时，声网会发送 `connectionChangedToState` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-2]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-oc.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannelByToken` 请求。
- T1：调用 `joinChannelByToken` 200 ms 后，UID1 加入频道。同时，UID1 收到 `connectionChangedToState(Connecting, Connecting)` 回调。成功加入频道后，UID1 收到 `connectionChangedToState(Connected, JoinSuccess)` 和 `didJoinChannel` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `didJoinedOfUid` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `rtcEngineConnectionDidLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `didOfflineOfUid` 回调。
- T7：如果 UID 1 收到 `connectionChangedToState(Reconnecting, Interrupted)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `connectionChangedToState(Failed, JoinFailed)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-2]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-2]

本节介绍如何使用 `connectionChangedToState` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `AgoraRtcEngineDelegate` 的文件，将以下代码复制到 `AgoraRtcEngineDelegate` 初始化过程中。

```swift
func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionState, reason: AgoraConnectionChangedReason) {
    LogUtils.log(message: "Connection state changed: \(state) \(reason)", level: .info)
}
```

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`connectionChangedToState` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-2]

### 连接状态 [#连接状态-5]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-ios-macos-markdown-0-1-1 details](#table-slot-channel-connection-ios-macos-markdown-0-1-1-1) |
| Connecting | 调用 `didJoinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `didJoinChannel` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-ios-macos-markdown-0-4-1 details](#table-slot-channel-connection-ios-macos-markdown-0-4-1-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannelByToken` 再次加入频道。 |

<a id="table-slot-channel-connection-ios-macos-markdown-0-1-1-1"></a>

**channel-connection-ios-macos-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannelByToken` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-ios-macos-markdown-0-4-1-1"></a>

**channel-connection-ios-macos-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `didRejoinChannel` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `connectionChangedToState(Reconnecting, Lost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-2]

`connectionChangedToState` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-ios-macos-markdown-1-1-1 details](#table-slot-channel-connection-ios-macos-markdown-1-1-1-1) |
| Connecting | [channel-connection-ios-macos-markdown-1-2-1 details](#table-slot-channel-connection-ios-macos-markdown-1-2-1-1) |
| Connected | [channel-connection-ios-macos-markdown-1-3-1 details](#table-slot-channel-connection-ios-macos-markdown-1-3-1-1) |
| Reconnecting | [channel-connection-ios-macos-markdown-1-4-1 details](#table-slot-channel-connection-ios-macos-markdown-1-4-1-1) |
| Failed | [channel-connection-ios-macos-markdown-1-5-1 details](#table-slot-channel-connection-ios-macos-markdown-1-5-1-1) |

<a id="table-slot-channel-connection-ios-macos-markdown-1-1-1-1"></a>

**channel-connection-ios-macos-markdown-1-1-1 details**

- `LeaveChannel`(5)：用户离开频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-2-1-1"></a>

**channel-connection-ios-macos-markdown-1-2-1 details**

- `Connecting`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-3-1-1"></a>

**channel-connection-ios-macos-markdown-1-3-1 details**

- `JoinSuccess`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-ios-macos-markdown-1-4-1-1"></a>

**channel-connection-ios-macos-markdown-1-4-1 details**

- `Interrupted`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `Lost`(16)：SDK 和服务器失去连接。
- `SettingProxyServer`(11)：由于设置了代理服务器，SDK 尝试重连。
- `ClientIpAddressChanged`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KeepAliveTimeout`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RenewToken`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-ios-macos-markdown-1-5-1-1"></a>

**channel-connection-ios-macos-markdown-1-5-1 details**

- `BannedByServer`(3)：用户被服务器禁止。
- `JoinFailed`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannelByToken` 重新加入频道。
- `InvalidAppId`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `InvalidChannelName`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。
- `TokenExpired`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用  `joinChannelByToken` 加入频道。
- `RejectedByServer`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 调用 `joinChannelByToken`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-2]

- [`getConnectionState`](/zh-CN/api-reference/rtc/macos/network#api_irtcengine_getconnectionstate)
- [`connectionChangedToState`](/zh-CN/api-reference/rtc/macos/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
本文介绍声网频道如何判断用户在通信的各个阶段处于什么连接状态以及各状态的转变过程。

## 获取连接状态 [#获取连接状态]

为帮助开发者更好地了解和管理用户在频道内的连接状态，声网 Web SDK 提供 [`AgoraRTCClient.connectionState`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#connectionstate) 字段和 [`AgoraRTCClient.on("connection-state-change")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_connection_state_change) 回调帮助你获取当前的连接状态。

当用户连接状态发生改变时，SDK 会触发 [`AgoraRTCClient.on("connection-state-change")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_connection_state_change) 回调，并在回调中明确当前的连接状态和发生状态改变的原因。

下面列出所有的连接状态：

- `"DISCONNECTED"`: 连接断开。处于这个状态时，SDK 不会自动重连。该状态表示用户处于以下任一阶段：

  - 尚未通过 `join` 加入频道。
  - 已经通过 `leave` 离开频道。
  - 被声网服务器踢出频道或者连接失败等异常情况。

- `"CONNECTING"`: 正在连接。调用 `join` 时为此状态。

- `"CONNECTED"`: 已连接。该状态表示用户已经加入频道，可以在频道内发布或订阅媒体轨道。

- `"RECONNECTING"`: 连接断开，正在尝试重连。因网络断开或切换导致 SDK 与服务器的连接中断，SDK 会自动重连，进入此状态。

- `"DISCONNECTING"`: 正在断开连接。调用 `leave` 时为此状态。

下图展示连接状态发生改变的触发时机：

![触发时机](https://web-cdn.agora.io/doc-cms/uploads/1728356279197-reconnect-web.png)

## 断线重连机制 [#断线重连机制]

通信过程中，如果 SDK 因网络等原因，断开与服务器的连接，SDK 会自动开启断线重连机制。

下图展示从本地用户 UID 1 加入频道，到连接中断，再到连接完全失败过程中，本地用户 UID 1 和远端用户 UID 2 会收到的回调：

![回调](https://web-cdn.agora.io/doc-cms/uploads/1728375984513-web-connection-state.png)

其中：

- T0：SDK 接收到 UID 1 的 `Client.join` 请求。
- T1：UID 1 成功加入频道。加入频道过程中，UID 1 会收到 `AgoraRTCClient.on("connection-state-change")` 回调报告 `"CONNECTING"`，加入后报告 `"CONNECTED"`。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `AgoraRTCClient.on("user-joined")` 回调。
- T3：某个时间点 UID 1 调用 `AgoraRTCClient.publish` 发布本地轨道。
- T4：UID 2 收到 `AgoraRTCClient.on("user-published")` 回调，表示 UID 1 已发布轨道。UID 2 可以调用 `AgoraRTCClient.subscribe` 方法订阅 UID 1 的轨道。
- T5：通信过程中 UID 1 网络发生中断，SDK 自动开启断线重连机制。
- T6：SDK 自动重连过程中，触发 `AgoraRTCClient.on("connection-state-change")` 回调报告 `"RECONNECTING"`。
- T7：如果声网服务器连续 10 秒没有收到 UID 1 的音视频包，声网服务器判断 UID 1 不再发布音视频，UID 2 会收到 `AgoraRTCClient.on("user-unpublished")` 回调。
- T8：如果声网服务器连续 20 秒没有收到 UID 1 的心跳包，声网服务器判断 UID 1 离线，UID 2 会收到 `AgoraRTCClient.on("user-left")` 回调。
- T9：成功重新建立连接后，UID 1 会收到 `AgoraRTCClient.on("connection-state-change")` 回调报告 `"CONNECTED"`。
- T10：UID 2 再次收到 `AgoraRTCClient.on("user-joined")` 回调。

## API 参考 [#api-参考-3]

- [`AgoraRTCClient.on("connection-state-change")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_connection_state_change)
- [`AgoraRTCClient.on("user-joined")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_user_joined)
- [`AgoraRTCClient.on("user-left")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_user_left)
- [`AgoraRTCClient.on("user-published")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_user_published)
- [`AgoraRTCClient.on("user-unpublished")`](/zh-CN/api-reference/rtc/web/interfaces/iagorartcclient#event_user_unpublished)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="windows" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-3]

### 连接状态 [#连接状态-6]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-3]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `onConnectionStateChanged(CONNECTING, CONNECTING)` 回调。成功加入频道后，UID1 收到 `onConnectionStateChanged(CONNECTED, JOIN_SUCCESS)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(FAILED, JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-3]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-3]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，在 `IRtcEngineEventHandler` 初始化进程中加入 `onConnectionStateChanged`。

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-3]

### 连接状态 [#连接状态-7]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-windows-unreal-cpp-markdown-0-1-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-0-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-windows-unreal-cpp-markdown-0-4-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-0-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-0-4-1"></a>

**channel-connection-windows-unreal-cpp-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(RECONNECTING, LOST)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-3]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-windows-unreal-cpp-markdown-1-1-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-1-1) |
| Connecting | [channel-connection-windows-unreal-cpp-markdown-1-2-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-2-1) |
| Connected | [channel-connection-windows-unreal-cpp-markdown-1-3-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-3-1) |
| Reconnecting | [channel-connection-windows-unreal-cpp-markdown-1-4-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-4-1) |
| Failed | [channel-connection-windows-unreal-cpp-markdown-1-5-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-5-1) |

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-2-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-3-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-4-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-5-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-4]

- [`getConnectionState`](/zh-CN/api-reference/rtc/cpp-all-platforms/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/cpp-all-platforms/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-4]

### 连接状态 [#连接状态-8]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-4]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `onConnectionStateChanged(CONNECTING, CONNECTING)` 回调。 成功加入频道后，UID1 收到 `onConnectionStateChanged(CONNECTED, JOIN_SUCCESS)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(FAILED, JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-4]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-4]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，将以下代码复制到 `IRtcEngineEventHandler` 初始化过程中。

```arkts
config.mEventHandler.onConnectionStateChanged = (
    state: Constants.ConnectionState,
    reason: Constants.ConnectionChangedReason
) => {
    Logger.info(TAG, `onConnectionStateChanged state=${state} reason=${reason}`);
};
```

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-4]

### 连接状态 [#连接状态-9]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| DISCONNECTED | [channel-connection-harmonyos-markdown-0-1-1 details](#table-slot-channel-connection-harmonyos-markdown-0-1-1) |
| CONNECTING | 调用 `joinChannel` 方法后的瞬时状态。 |
| CONNECTED | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。 此时用户可以发布或订阅频道中的音频和视频。 |
| RECONNECTING | [channel-connection-harmonyos-markdown-0-4-1 details](#table-slot-channel-connection-harmonyos-markdown-0-4-1) |
| FAILED | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-harmonyos-markdown-0-1-1"></a>

**channel-connection-harmonyos-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-harmonyos-markdown-0-4-1"></a>

**channel-connection-harmonyos-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(RECONNECTING, LOST)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-4]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| DISCONNECTED | [channel-connection-harmonyos-markdown-1-1-1 details](#table-slot-channel-connection-harmonyos-markdown-1-1-1) |
| CONNECTING | [channel-connection-harmonyos-markdown-1-2-1 details](#table-slot-channel-connection-harmonyos-markdown-1-2-1) |
| CONNECTED | [channel-connection-harmonyos-markdown-1-3-1 details](#table-slot-channel-connection-harmonyos-markdown-1-3-1) |
| RECONNECTING | [channel-connection-harmonyos-markdown-1-4-1 details](#table-slot-channel-connection-harmonyos-markdown-1-4-1) |
| FAILED | [channel-connection-harmonyos-markdown-1-5-1 details](#table-slot-channel-connection-harmonyos-markdown-1-5-1) |

<a id="table-slot-channel-connection-harmonyos-markdown-1-1-1"></a>

**channel-connection-harmonyos-markdown-1-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-harmonyos-markdown-1-2-1"></a>

**channel-connection-harmonyos-markdown-1-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-harmonyos-markdown-1-3-1"></a>

**channel-connection-harmonyos-markdown-1-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-harmonyos-markdown-1-4-1"></a>

**channel-connection-harmonyos-markdown-1-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-harmonyos-markdown-1-5-1"></a>

**channel-connection-harmonyos-markdown-1-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-5]

- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/harmonyos/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="electron" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-5]

### 连接状态 [#连接状态-10]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-5]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID 1) 和远程用户 (UID 2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-framework.png)

图解如下：

- T0：SDK 接收到 UID 1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID 1 收到 `onConnectionStateChanged(connectionStateConnecting, connectionChangedConnecting)` 回调。成功加入频道后，UID 1 收到 `onConnectionStateChanged(connectionStateConnected, connectionChangedJoinSuccess)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID 1 连续 4 秒没有收到服务器发送的任何数据，UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID 2 连续 20 秒没有收到来自 UID 1 的任何数据，则 SDK 判断 UID 1 离线。UID 2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(connectionStateFailed, connectionChangedJoinFailed)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-5]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-5]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，在 `IRtcEngineEventHandler` 初始化过程中加入 `onConnectionStateChanged`。

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-5]

### 连接状态 [#连接状态-11]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-electron-rn-markdown-0-1-1 details](#table-slot-channel-connection-electron-rn-markdown-0-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。 此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-electron-rn-markdown-0-4-1 details](#table-slot-channel-connection-electron-rn-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-electron-rn-markdown-0-1-1"></a>

**channel-connection-electron-rn-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-electron-rn-markdown-0-4-1"></a>

**channel-connection-electron-rn-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedLost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-5]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-electron-rn-markdown-1-1-1 details](#table-slot-channel-connection-electron-rn-markdown-1-1-1) |
| Connecting | [channel-connection-electron-rn-markdown-1-2-1 details](#table-slot-channel-connection-electron-rn-markdown-1-2-1) |
| Connected | [channel-connection-electron-rn-markdown-1-3-1 details](#table-slot-channel-connection-electron-rn-markdown-1-3-1) |
| Reconnecting | [channel-connection-electron-rn-markdown-1-4-1 details](#table-slot-channel-connection-electron-rn-markdown-1-4-1) |
| Failed | [channel-connection-electron-rn-markdown-1-5-1 details](#table-slot-channel-connection-electron-rn-markdown-1-5-1) |

<a id="table-slot-channel-connection-electron-rn-markdown-1-1-1"></a>

**channel-connection-electron-rn-markdown-1-1-1 details**

- `LeaveChannel`(5)：用户离开频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-2-1"></a>

**channel-connection-electron-rn-markdown-1-2-1 details**

- `Connecting`(0)：App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-3-1"></a>

**channel-connection-electron-rn-markdown-1-3-1 details**

- `JoinSuccess`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-4-1"></a>

**channel-connection-electron-rn-markdown-1-4-1 details**

- `Interrupted`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `Lost`(16)：SDK 和服务器失去连接。
- `SettingProxyServer`(11)：由于设置了代理服务器，SDK 尝试重连。
- `ClientIpAddressChanged`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KeepAliveTimeout`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RenewToken`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-electron-rn-markdown-1-5-1"></a>

**channel-connection-electron-rn-markdown-1-5-1 details**

- `BannedByServer`(3)：用户被服务器禁止。
- `JoinFailed`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `InvalidAppId`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `InvalidChannelName`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TokenExpired`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `RejectedByServer`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-6]

- [`getConnectionState`](/zh-CN/api-reference/rtc/electron/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/electron/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-6]

### 连接状态 [#连接状态-12]

当连接状态发生变化时，声网会发送 `OnConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-6]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-unity.png)

图解如下：

- T0：SDK 接收到 UID1 的 `JoinChannel` 请求。
- T1：调用 `JoinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `OnConnectionStateChanged(CONNECTION_STATE_CONNECTING, CONNECTION_CHANGED_CONNECTING)` 回调。成功加入频道后，UID1 收到 `OnConnectionStateChanged(CONNECTION_STATE_CONNECTING, CONNECTION_CHANGED_JOIN_SUCCESS)` 和 `OnJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `OnUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `OnConnectionStateChanged(CONNECTION_STATE_RECONNECTING, CONNECTION_CHANGED_INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `OnConnectionStateChanged(CONNECTION_STATE_RECONNECTING, CONNECTION_CHANGED_INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `OnConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `OnUserOffline` 回调。
- T7：如果 UID 1 收到 `OnConnectionStateChanged(CONNECTION_STATE_RECONNECTING, CONNECTION_CHANGED_INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `OnConnectionStateChanged(CONNECTION_STATE_FAILED, CONNECTION_CHANGED_JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-6]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-6]

本节介绍如何使用 `OnConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，在 `IRtcEngineEventHandler` 初始化进程中加入 `OnConnectionStateChanged`。

```csharp
internal class UserEventHandler : IRtcEngineEventHandler
{
    ...
    // 频道连接状态发生变化回调
    public override void OnConnectionStateChanged(RtcConnection connection, CONNECTION_STATE_TYPE state,
        CONNECTION_CHANGED_REASON_TYPE reason)
    {
        _helloVideoTokenAgora._state = state;
    }
}
```

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`OnConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-6]

### 连接状态 [#连接状态-13]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-unity-markdown-0-1-1 details](#table-slot-channel-connection-unity-markdown-0-1-1) |
| Connecting | 调用 `JoinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `OnJoinChannelSuccess` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-unity-markdown-0-4-1 details](#table-slot-channel-connection-unity-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `LeaveChannel` 离开当前频道，再调用 `JoinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-unity-markdown-0-1-1"></a>

**channel-connection-unity-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `JoinChannel` 之前。
- 调用 `LeaveChannel` 之后。

<a id="table-slot-channel-connection-unity-markdown-0-4-1"></a>

**channel-connection-unity-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `OnRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `OnConnectionStateChanged(RECONNECTING, LOST)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-6]

`OnConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-unity-markdown-1-1-1 details](#table-slot-channel-connection-unity-markdown-1-1-1) |
| Connecting | [channel-connection-unity-markdown-1-2-1 details](#table-slot-channel-connection-unity-markdown-1-2-1) |
| Connected | [channel-connection-unity-markdown-1-3-1 details](#table-slot-channel-connection-unity-markdown-1-3-1) |
| Reconnecting | [channel-connection-unity-markdown-1-4-1 details](#table-slot-channel-connection-unity-markdown-1-4-1) |
| Failed | [channel-connection-unity-markdown-1-5-1 details](#table-slot-channel-connection-unity-markdown-1-5-1) |

<a id="table-slot-channel-connection-unity-markdown-1-1-1"></a>

**channel-connection-unity-markdown-1-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-unity-markdown-1-2-1"></a>

**channel-connection-unity-markdown-1-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-unity-markdown-1-3-1"></a>

**channel-connection-unity-markdown-1-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-unity-markdown-1-4-1"></a>

**channel-connection-unity-markdown-1-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-unity-markdown-1-5-1"></a>

**channel-connection-unity-markdown-1-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `LeaveChannel` 离开当前频道，然后调用 `JoinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `JoinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `JoinChannel`。
  - App 调用了 `StartEchoTest`，但没有调用 `StopEchoTest` 结束回声测试。

### API 参考 [#api-参考-7]

- [`GetConnectionState`](/zh-CN/api-reference/rtc/unity/network#api_irtcengine_getconnectionstate)
- [`OnConnectionStateChanged`](/zh-CN/api-reference/rtc/unity/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-7]

### 连接状态 [#连接状态-14]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。 下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-7]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-framework.png)

图解如下：

- T0：SDK 接收到 UID 1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID 1 收到 `onConnectionStateChanged(connectionStateConnecting, connectionChangedConnecting)` 回调。成功加入频道后，UID 1 收到 `onConnectionStateChanged(connectionStateConnected, connectionChangedJoinSuccess)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID 1 连续 4 秒没有收到服务器发送的任何数据，UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID 2 连续 20 秒没有收到来自 UID 1 的任何数据，则 SDK 判断 UID 1 离线。UID 2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(connectionStateFailed, connectionChangedJoinFailed)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-7]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-7]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `RtcEngineEventHandler` 的文件，在 `RtcEngineEventHandler` 初始化过程中加入 `onConnectionStateChanged`。

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-7]

### 连接状态 [#连接状态-15]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-flutter-markdown-0-1-1 details](#table-slot-channel-connection-flutter-markdown-0-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。 此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-flutter-markdown-0-4-1 details](#table-slot-channel-connection-flutter-markdown-0-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-flutter-markdown-0-1-1"></a>

**channel-connection-flutter-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-flutter-markdown-0-4-1"></a>

**channel-connection-flutter-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedLost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-7]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-flutter-markdown-1-1-1 details](#table-slot-channel-connection-flutter-markdown-1-1-1) |
| Connecting | [channel-connection-flutter-markdown-1-2-1 details](#table-slot-channel-connection-flutter-markdown-1-2-1) |
| Connected | [channel-connection-flutter-markdown-1-3-1 details](#table-slot-channel-connection-flutter-markdown-1-3-1) |
| Reconnecting | [channel-connection-flutter-markdown-1-4-1 details](#table-slot-channel-connection-flutter-markdown-1-4-1) |
| Failed | [channel-connection-flutter-markdown-1-5-1 details](#table-slot-channel-connection-flutter-markdown-1-5-1) |

<a id="table-slot-channel-connection-flutter-markdown-1-1-1"></a>

**channel-connection-flutter-markdown-1-1-1 details**

- `LeaveChannel`(5)：用户离开频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-flutter-markdown-1-2-1"></a>

**channel-connection-flutter-markdown-1-2-1 details**

- `Connecting`(0)：App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-flutter-markdown-1-3-1"></a>

**channel-connection-flutter-markdown-1-3-1 details**

- `JoinSuccess`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-flutter-markdown-1-4-1"></a>

**channel-connection-flutter-markdown-1-4-1 details**

- `Interrupted`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `Lost`(16)：SDK 和服务器失去连接。
- `SettingProxyServer`(11)：由于设置了代理服务器，SDK 尝试重连。
- `ClientIpAddressChanged`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KeepAliveTimeout`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RenewToken`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-flutter-markdown-1-5-1"></a>

**channel-connection-flutter-markdown-1-5-1 details**

- `BannedByServer`(3)：用户被服务器禁止。
- `JoinFailed`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `InvalidAppId`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `InvalidChannelName`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TokenExpired`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `RejectedByServer`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-8]

- [`getConnectionState`](/zh-CN/api-reference/rtc/flutter/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/flutter/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="react-native" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-8]

### 连接状态 [#连接状态-16]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-8]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID 1) 和远程用户 (UID 2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection-framework.png)

图解如下：

- T0：SDK 接收到 UID 1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID 1 收到 `onConnectionStateChanged(connectionStateConnecting, connectionChangedConnecting)` 回调。成功加入频道后，UID 1 收到 `onConnectionStateChanged(connectionStateConnected, connectionChangedJoinSuccess)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID 1 连续 4 秒没有收到服务器发送的任何数据，UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID 2 连续 20 秒没有收到来自 UID 1 的任何数据，则 SDK 判断 UID 1 离线。UID 2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedInterrupted)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(connectionStateFailed, connectionChangedJoinFailed)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-8]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-8]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，在 `IRtcEngineEventHandler` 初始化过程中加入 `onConnectionStateChanged`。

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。 有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-8]

### 连接状态 [#连接状态-17]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-electron-rn-markdown-0-1-1 details](#table-slot-channel-connection-electron-rn-markdown-0-1-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。 此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-electron-rn-markdown-0-4-1 details](#table-slot-channel-connection-electron-rn-markdown-0-4-1-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-electron-rn-markdown-0-1-1-1"></a>

**channel-connection-electron-rn-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-electron-rn-markdown-0-4-1-1"></a>

**channel-connection-electron-rn-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(connectionStateReconnecting, connectionChangedLost)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-8]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-electron-rn-markdown-1-1-1 details](#table-slot-channel-connection-electron-rn-markdown-1-1-1-1) |
| Connecting | [channel-connection-electron-rn-markdown-1-2-1 details](#table-slot-channel-connection-electron-rn-markdown-1-2-1-1) |
| Connected | [channel-connection-electron-rn-markdown-1-3-1 details](#table-slot-channel-connection-electron-rn-markdown-1-3-1-1) |
| Reconnecting | [channel-connection-electron-rn-markdown-1-4-1 details](#table-slot-channel-connection-electron-rn-markdown-1-4-1-1) |
| Failed | [channel-connection-electron-rn-markdown-1-5-1 details](#table-slot-channel-connection-electron-rn-markdown-1-5-1-1) |

<a id="table-slot-channel-connection-electron-rn-markdown-1-1-1-1"></a>

**channel-connection-electron-rn-markdown-1-1-1 details**

- `LeaveChannel`(5)：用户离开频道。
- `InvalidToken`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-2-1-1"></a>

**channel-connection-electron-rn-markdown-1-2-1 details**

- `Connecting`(0)：App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-3-1-1"></a>

**channel-connection-electron-rn-markdown-1-3-1 details**

- `JoinSuccess`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-electron-rn-markdown-1-4-1-1"></a>

**channel-connection-electron-rn-markdown-1-4-1 details**

- `Interrupted`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `Lost`(16)：SDK 和服务器失去连接。
- `SettingProxyServer`(11)：由于设置了代理服务器，SDK 尝试重连。
- `ClientIpAddressChanged`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KeepAliveTimeout`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RenewToken`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-electron-rn-markdown-1-5-1-1"></a>

**channel-connection-electron-rn-markdown-1-5-1 details**

- `BannedByServer`(3)：用户被服务器禁止。
- `JoinFailed`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `InvalidAppId`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `InvalidChannelName`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TokenExpired`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `RejectedByServer`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### API 参考 [#api-参考-9]

- [`getConnectionState`](/zh-CN/api-reference/rtc/react-native/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/react-native/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unreal" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-9]

### 连接状态 [#连接状态-18]

当连接状态发生变化时，声网会发送 `onConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

<a id="reconnection"></a>
### 断线重连 [#断线重连-9]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户 (UID1) 和远程用户 (UID2) 在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection/channel-connection.png)

图解如下：

- T0：SDK 接收到 UID1 的 `joinChannel` 请求。
- T1：调用 `joinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `onConnectionStateChanged(CONNECTING, CONNECTING)` 回调。成功加入频道后，UID1 收到 `onConnectionStateChanged(CONNECTED, JOIN_SUCCESS)` 和 `onJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `onUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `onConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `onUserOffline` 回调。
- T7：如果 UID 1 收到 `onConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `onConnectionStateChanged(FAILED, JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-9]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 操作步骤 [#操作步骤-9]

本节介绍如何使用 `onConnectionStateChanged` 回调来监控频道连接状态的变化。

在你的项目中，打开管理 `IRtcEngineEventHandler` 的文件，在 `IRtcEngineEventHandler` 初始化进程中加入 `onConnectionStateChanged`。

你可以从日志中读取当前连接状态，以及状态更改的触发原因。

另外，`onConnectionStateChanged` 中的 `reason` 参数也解释了连接状态改变的原因，可帮助你进行网络故障排除。有关频道连接状态变化的原因以及排障方式，详见[状态说明及排障指导](#connection_reason)。

## 参考信息 [#参考信息-9]

### 连接状态 [#连接状态-19]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-windows-unreal-cpp-markdown-0-1-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-0-1-1-1) |
| Connecting | 调用 `joinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `onJoinChannelSuccess` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-windows-unreal-cpp-markdown-0-4-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-0-4-1-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。 此时需调用 `leaveChannel` 离开当前频道，再调用 `joinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-0-1-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-0-1-1 details**

初始连接状态。它通常发生在：

- 调用 `joinChannel` 之前。
- 调用 `leaveChannel` 之后。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-0-4-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-0-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `onRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `onConnectionStateChanged(RECONNECTING, LOST)`，同时继续尝试重新加入频道。

<a id="connection_reason"></a>
### 状态说明及排障指导 [#状态说明及排障指导-9]

`onConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-windows-unreal-cpp-markdown-1-1-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-1-1-1) |
| Connecting | [channel-connection-windows-unreal-cpp-markdown-1-2-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-2-1-1) |
| Connected | [channel-connection-windows-unreal-cpp-markdown-1-3-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-3-1-1) |
| Reconnecting | [channel-connection-windows-unreal-cpp-markdown-1-4-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-4-1-1) |
| Failed | [channel-connection-windows-unreal-cpp-markdown-1-5-1 details](#table-slot-channel-connection-windows-unreal-cpp-markdown-1-5-1-1) |

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-1-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-2-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-3-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-4-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。 关于自动重连时连接状态如何改变， 详见[断线重连](#reconnection)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-windows-unreal-cpp-markdown-1-5-1-1"></a>

**channel-connection-windows-unreal-cpp-markdown-1-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。 你需要调用 `leaveChannel` 离开当前频道，然后调用 `joinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `startEchoTest`，但没有调用 `stopEchoTest` 结束回声测试。

### 示例项目 [#示例项目]

声网提供了开源的示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title="Unreal C++ 示例项目" href="https://github.com/AgoraIO-Extensions/Agora-Unreal-RTC-SDK/tree/main/Agora-Unreal-SDK-CPP-Example" />
</Cards>

### API 参考 [#api-参考-10]

- [`getConnectionState`](/zh-CN/api-reference/rtc/unreal-cpp/network#api_irtcengine_getconnectionstate)
- [`onConnectionStateChanged`](/zh-CN/api-reference/rtc/unreal-cpp/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="blueprint" />
在实时音视频场景下，App 端与声网 SD-RTN™ 之间的连接状态会随着客户端加入或离开频道而发生变化，也可能由于网络或鉴权问题而导致连接中断。

本文介绍各种频道连接状态，状态改变原因和处理方式，帮助你更好地管理用户和排除网络故障。

## 技术原理 [#技术原理-10]

### 连接状态 [#连接状态-20]

当连接状态发生变化时，声网会发送 `FOnConnectionStateChanged` 回调。下图展示各种连接状态，以及用户从加入到离开频道的过程中连接状态如何改变：

<DocsImage alt="连接状态" src="https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection.svg" displayWidth="80%" />

### 断线重连 [#断线重连-10]

通信过程中，如果因网络问题导致连接断开，SDK 会自动开启断线重连机制。下图展示本地用户（UID1）和远程用户（UID2）在以下过程中收到的回调：本地用户加入频道、发生网络异常、连接中断、重新加入频道。

![重连时序图](https://web-cdn.agora.io/docs-files/1695362828569)

图解如下：

- T0：SDK 接收到 UID1 的 `JoinChannel` 请求。
- T1：调用 `JoinChannel` 200 ms 后，UID1 加入频道。同时，UID1 收到 `FOnConnectionStateChanged(CONNECTING, CONNECTING)` 回调。成功加入频道后，UID1 收到 `FOnConnectionStateChanged(CONNECTED, JOIN_SUCCESS)` 和 `FOnJoinChannelSuccess` 回调。
- T2：因网间传输延迟，UID 2 感知 UID 1 加入频道约有 100 毫秒的延迟，此时 UID 2 收到 `FOnUserJoined` 回调。
- T3：某个时间点 UID 1 客户端因断网等原因导致上行网络变差。SDK 自动尝试重新加入频道。
- T4：如果 UID1 连续 4 秒没有收到服务器发送的任何数据，UID1 收到 `FOnConnectionStateChanged(RECONNECTING, INTERRUPTED)` 回调；同时 SDK 继续尝试重新加入频道。
- T5：如果 UID 1 收到 `FOnConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 10 秒没有收到服务器发送的任何数据，UID 1 会收到 `FOnConnectionLost` 回调；同时 SDK 继续尝试重新加入频道。
- T6：如果 UID2 连续 20 秒没有收到来自 UID1 的任何数据，则 SDK 判断 UID1 离线。UID2 收到 `FOnUserOffline` 回调。
- T7：如果 UID 1 收到 `FOnConnectionStateChanged(RECONNECTING, INTERRUPTED)` 后连续 20 分钟无法重新加入频道，SDK 不再继续尝试。UID 1 收到 `FOnConnectionStateChanged(FAILED, JOIN_FAILED)` 回调；用户需要退出当前频道，然后重新加入频道。

## 前提条件 [#前提条件-10]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 实现方法 [#实现方法]

本节介绍如何使用 `FOnConnectionStateChanged` 回调来监控频道连接状态的变化。

1. 创建 **OnConnectionStateChanged** 回调函数，配置以下参数：

    | 输入参数 | 数据类型 | 参数描述 |
    |:-------|:--------|:---------|
    | `state` | Enum | 当前网络连接状态。详见 [`ECONNECTION_STATE_TYPE`](/zh-CN/api-reference/rtc/unreal-blueprint/enum-connectionstatetype)。|
    | `reason` | Enum | 引起当前网络连接状态改变的原因。详见 [`ECONNECTION_CHANGED_REASON_TYPE`](/zh-CN/api-reference/rtc/unreal-blueprint/enum-connectionchangedreasontype)。|

2. 添加对 **OnConnectionStateChanged** 回调的监听，如下图所示：

![监听 OnConnectionStateChanged 回调](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection-event.png)

3. 当频道连接状态发生变化，触发 **OnConnectionStateChanged** 回调时，打印监听到的网络连接状态信息。你可以从日志中读取当前连接状态以及状态更改的触发原因，进而帮助网络故障排查，详见[状态说明及排障指导](#状态说明及排障指导-10)。如下图所示：

![频道连接状态日志示例](https://web-cdn.agora.io/docs-portal/img/rtc/channel-connection-log.png)

## 参考信息 [#参考信息-10]

### 连接状态 [#连接状态-21]

如前文图中所示，App 在加入和离开频道前后可能出现以下 5 种连接状态：

| 连接状态 | 描述 |
| --- | --- |
| Disconnected | [channel-connection-unreal-blueprint-markdown-1-1-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-1-1-1) |
| Connecting | 调用 `JoinChannel` 方法后的瞬时状态。 |
| Connected | 发生在 App 成功加入频道后。SDK 还会触发 `FOnJoinChannelSuccess` 回调，上报本地客户端已经加入频道。此时用户可以发布或订阅频道中的音频和视频。 |
| Reconnecting | [channel-connection-unreal-blueprint-markdown-1-4-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-1-4-1) |
| Failed | 连接失败。发生在 SDK 在 20 分钟内无法加入频道、并且 SDK 停止重新连接频道时。此时需调用 `LeaveChannel` 离开当前频道，再调用 `JoinChannel` 再次加入频道。 |

<a id="table-slot-channel-connection-unreal-blueprint-markdown-1-1-1"></a>

**channel-connection-unreal-blueprint-markdown-1-1-1 details**

初始连接状态。它通常发生在：

- 调用 `JoinChannel` 之前。
- 调用 `LeaveChannel` 之后。

<a id="table-slot-channel-connection-unreal-blueprint-markdown-1-4-1"></a>

**channel-connection-unreal-blueprint-markdown-1-4-1 details**

发生在连接中断时。SDK 会在中断后自动尝试重新连接。

- 如果重新加入频道成功，SDK 会触发 `FOnRejoinChannelSuccess` 回调。
- 如果 10 秒内没有加入频道，SDK 会触发 `FOnConnectionStateChanged(RECONNECTING, LOST)`，同时继续尝试重新加入频道。

### 状态说明及排障指导 [#状态说明及排障指导-10]

`FOnConnectionStateChanged` 中的 `reason` 参数描述了连接状态更改原因。

下表列出了不同连接状态和状态变化原因之间的映射关系，以及发生网络中断时故障时的处理方法。

| 连接状态 | 状态说明和排障指导 |
| --- | --- |
| Disconnected | [channel-connection-unreal-blueprint-markdown-2-1-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-2-1-1) |
| Connecting | [channel-connection-unreal-blueprint-markdown-2-2-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-2-2-1) |
| Connected | [channel-connection-unreal-blueprint-markdown-2-3-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-2-3-1) |
| Reconnecting | [channel-connection-unreal-blueprint-markdown-2-4-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-2-4-1) |
| Failed | [channel-connection-unreal-blueprint-markdown-2-5-1 details](#table-slot-channel-connection-unreal-blueprint-markdown-2-5-1) |

<a id="table-slot-channel-connection-unreal-blueprint-markdown-2-1-1"></a>

**channel-connection-unreal-blueprint-markdown-2-1-1 details**

- `LEAVE_CHANNEL`(5)：用户离开频道。
- `INVALID_TOKEN`(8)：Token 无效，请使用有效的 Token 加入频道。

<a id="table-slot-channel-connection-unreal-blueprint-markdown-2-2-1"></a>

**channel-connection-unreal-blueprint-markdown-2-2-1 details**

- `CONNECTING`(0): App 正在尝试加入声网频道。

<a id="table-slot-channel-connection-unreal-blueprint-markdown-2-3-1"></a>

**channel-connection-unreal-blueprint-markdown-2-3-1 details**

- `JOIN_SUCCESS`(1)：App 已成功加入频道。

<a id="table-slot-channel-connection-unreal-blueprint-markdown-2-4-1"></a>

**channel-connection-unreal-blueprint-markdown-2-4-1 details**

- `INTERRUPTED`(2)：当网络连接中断时，SDK 自动重新连接频道，连接状态持续变化。关于自动重连时连接状态如何改变， 详见[断线重连](#断线重连-10)。
- `LOST`(16)：SDK 和服务器失去连接。
- `SETTING_PROXY_SERVER`(11)：由于设置了代理服务器，SDK 尝试重连。
- `CLIENT_IP_ADDRESS_CHANGED`(13)：客户端 IP 地址变更。如多次收到该状态码，请提示用户更换网络后尝试重新加入频道。
- `KEEP_ALIVE_TIMEOUT`(14)：SDK 和服务器连接保活超时，进入自动重连状态。
- `RENEW_TOKEN`(12)：更新 Token 引起网络连接状态改变。

<a id="table-slot-channel-connection-unreal-blueprint-markdown-2-5-1"></a>

**channel-connection-unreal-blueprint-markdown-2-5-1 details**

- `BANNED_BY_SERVER`(3)：用户被服务器禁止。
- `JOIN_FAILED`(4)：SDK 在 20 分钟内持续尝试加入频道失败，停止尝试重连。你需要调用 `LeaveChannel` 离开当前频道，然后调用 `JoinChannel` 重新加入频道。
- `INVALID_APP_ID`(6)：App ID 无效，请使用有效的 App ID 加入频道。
- `INVALID_CHANNEL_NAME`(7)：频道名无效，请检查频道名中是否包含非法字符，并使用有效的频道名加入频道。
- `TOKEN_EXPIRED`(9)：Token 已过期。请从 App 服务器获取新的 Token，然后调用 `joinChannel` 重新加入频道。
- `REJECTED_BY_SERVER`(10)：此用户被服务器禁止。一般有以下原因：

  - 本地用户已加入频道后，App 再次调用加入频道的 API，如 `joinChannel`。
  - App 调用了 `StartEchoTest`，但没有调用 `StopEchoTest` 结束回声测试。

### 示例项目 [#示例项目-1]

声网提供了开源的示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title="Blueprint 示例项目" href="https://github.com/AgoraIO-Extensions/Agora-Unreal-RTC-SDK/tree/main/Agora-Unreal-SDK-Blueprint-Example" />
  <Card title="JoinChannelAudio" href="https://github.com/AgoraIO-Extensions/Agora-Unreal-RTC-SDK/tree/main/Agora-Unreal-SDK-Blueprint-Example/Content/API-Example/Basic/JoinChannelAudio" />
</Cards>

### API 参考 [#api-参考-11]

- [`GetConnectionState`](/zh-CN/api-reference/rtc/unreal-blueprint/network#api_irtcengine_getconnectionstate)
- [`FOnConnectionStateChanged`](/zh-CN/api-reference/rtc/unreal-blueprint/network#callback_irtcengineeventhandler_onconnectionstatechanged)
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
