# Connection basics (/en/realtime-media/rtm/build/connect-and-authenticate/connection/connection-management/flutter)

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

A Signaling client must establish a connection with the server to access network resources. API calls, messages, and events in the channel are transmitted through network connections. While the Signaling SDK manages establishing and maintaining network connections, understanding its management mechanism helps you handle potential network errors in the app, and improves the end user experience.

    This page shows how to manage the connection between the Signaling SDK and the Signaling server.

    ## Prerequisites [#prerequisites-7]

    Ensure that you have integrated the Signaling SDK in your project and implemented the framework functionality from the [SDK quickstart](../../../quickstart) page.

    ## Understand the tech [#understand-the-tech-4]

    The Signaling SDK abstracts the complexities of managing network connections and provides the `linkState` event notifications to inform users of various connection status transitions. To efficiently handle connection errors and manage the connection state, implement a listener for this event.

    <CalloutContainer type="info">
      <CalloutDescription>
        The `linkState` event is only available in Signaling `2.2.1` and above.
      </CalloutDescription>
    </CalloutContainer>

    It is important to understand that Signaling provides two types of services: `MESSAGE` services and `STREAM` services. The connection types corresponding to the two services are different. A client may use one or both of these services.

    ## Manage connections [#manage-connections-4]

    This section provides an overview of the types of Signaling connections. It discusses how to create a connection, monitor the connection state, configure timeout and reconnection behavior, and close connections when they are no longer needed.

    ### Create connection [#create-connection-4]

    When you create a Signaling client instance, or a stream channel instance, the Signaling SDK does not immediately establish a network connection with the server. At this point, you have just created an object instance for calling the Signaling SDK APIs. The client attempts to establish a network connection with the server only when you call `login` or `join`.

    #### Message connection [#message-connection-12]

    The `MESSAGE` service provides access to message channels, presence, storage, lock, token, and other functionalities. The messages, data, and event notifications of these functionalities share this connection. A connection only exists within the client life cycle. It is established when you call the `login` method to log in to the server, and ends when you call the `logout` method to log out of the server.

    To establish a `MESSAGE` connection, refer to the following code:

    ```dart
    try {
        var (status, response) = await rtmClient.login('your_Token');
        if (status.error == true ){
           print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
        } else {
            print('${status.operation} success!');
        }
    } catch (e) {
        print('something went wrong: $e');
    }
    ```

    <CalloutContainer type="info">
      <CalloutDescription>
        Establishing a `MESSAGE` connection increments the peak connections count.
      </CalloutDescription>
    </CalloutContainer>

    The `MESSAGE` connection is persistent. The client regularly sends heartbeat packets to the server to maintain activity. When you subscribe to multiple message channels, you receive all channel messages and event notifications through this connection.

    #### Stream connection [#stream-connection-14]

    The `STREAM` service provides users with all the capabilities of a stream channel. Unlike a `MESSAGE` connection, a `STREAM` connection is not globally unique. Each stream channel instance creates a separate connection. For example, when you create three stream channel instances and call the `join` method, the client establishes three network connections with the server.

    Before establishing a `STREAM` connection, you establish a `MESSAGE` connection. To do this, call the `login` method to log in to the server. The life cycle of a `STREAM` connection starts when you call `join` to join a channel and ends when you actively call `leave` to leave the channel. To establish a `STREAM` connection, refer to the following code:

    ```dart
    try {
        var (status,response) = await stChannel.join(token:'your_token',withPresence:true);
        if (status.error == true ){
           print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
        } else {
            print('${status.operation} success!');
        }
    } catch (e) {
        print('something went wrong: $e');
    }
    ```

    <CalloutContainer type="info">
      <CalloutDescription>
        Establishing a `STREAM` connection does not increase the peak connections count.
      </CalloutDescription>
    </CalloutContainer>

    A `STREAM` connection is also a persistent connection. The client sends heartbeat packets to the server at regular intervals to keep the connection active. The time interval for sending heartbeat packets is 0.5 seconds and cannot be changed. For application use-cases that require optimizing battery life, use of the `STREAM` service is not recommended.

    ### Monitoring the network connection [#monitoring-the-network-connection-4]

    The `linkState` callback provides event notifications for monitoring and managing the change of network connection status. By listening to this event, you can access crucial information such as:

    * The current state of the network connection.
    * The reasons or actions leading to the state change.
    * The previous network state before the change.
    * The timing of network connection state change.
    * The service type (message or stream) for which the connection status has changed.
    * Joined channels affected by the network state change.
    * Channels for which network connectivity was not successfully restored after the change.

    The detailed information provided by the event is valuable for handling business processes after recovering from unexpected disconnection states. It enables you to promptly identify and resolve issues caused by network connection changes, and ensures smooth business operations.

    To receive `linkState` notifications, refer to the following code:

    ```dart
    rtmClient.addListener(
        linkState: (event) {
            var currentState = event.currentState;
            var previousState = event.previousState;
            var serviceType = event.serviceType;
            var operation = event.operation;
            var reason = event.reason;
            var affectedChannels = event.affectedChannels;
            var unrestoredChannels = event.unrestoredChannels;
            var isResumed = event.isResumed;
            var timestamp = event.timestamp;
        }
    );
    ```

    The following table describes the available event parameters:

    | Attribute            | Description                                                                                                                                                           |
    | :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `currentState`       | The current connection state.                                                                                                                                         |
    | `previousState`      | The previous connection state.                                                                                                                                        |
    | `serviceType`        | The service type. `MESSAGE` or `STREAM`                                                                                                                               |
    | `operation`          | The operation that triggered this state change.                                                                                                                       |
    | `reason`             | Why the state change was triggered.                                                                                                                                   |
    | `affectedChannels`   | Channels affected by this state change.                                                                                                                               |
    | `unrestoredChannels` | Information about channels that have not been subscribed to or joined, including channel name, channel type, and temporary state data in the channel. Normally empty. |
    | `isResumed`          | Whether the connection state was restored from `disconnected` to `connecting` within 2 minutes after the disconnection. `true` indicates that it has been restored.   |
    | `timestamp`          | The timestamp when this event notification was sent.                                                                                                                  |

    ### Heartbeat detection [#heartbeat-detection-4]

    Heartbeat detection helps Signaling clients and servers detect sudden network disconnections, such as client network disconnection or network switching, in a timely manner.

    #### Message connection [#message-connection-13]

    The Signaling client automatically sends a ping packet to the server every 5 seconds by default. If the server does not respond with a pong packet within 10 seconds, the client interprets it as a network issue. Consequently, the client's network connection status (`RtmLinkState`) switches from `connecting` to `disconnected`, and it initiates reconnection attempts.

    Similarly, if the server does not receive a ping packet from the client within 15 seconds, it considers it a network problem on the client side. The server then waits for a predefined period (`presenceTimeout`). If the client fails to reconnect during this period, the Signaling server sends `remoteTimeout` event notifications to other users in the affected channel.

    It is important to note that the timeout mechanism applies only to accidental disconnections. Active disconnections, such as logging out by calling `logout`, do not trigger this behavior.

    The heartbeat interval is set to 5 seconds by default to balance device battery life and timely detection of network issues. However, you can customize this to increase battery life or to identify network disconnection in a more timely manner by specifying the `heartbeatInterval` parameter in `RtmConfig`. The supported range is \[5, 1800] seconds.

    While increasing `heartbeatInterval` saves battery, it delays detection of network issues and the peak connection count (PCU) may appear to be higher. Agora does not recommend setting the interval to the maximum value of 1800 seconds.

    To customize the heartbeat interval, refer to the following code:

    ```dart
    final userId = 'your_userId';
    final appId = 'your_appId';
    late RtmClient rtmClient;
    var privateConfig = RtmPrivateConfig(heartbeatInterval:30);
    var rtmConfig = RtmConfig( privateConfig:privateConfig );

    try {
        var (status,client) = await RTM(appId, userId, rtmConfig:rtmConfig);
        if (status.error == true) {
            print(status);
        } else {
            rtmClient = client;
            print('Initialize success!');
        }
    } catch (e) {
        print('Failed to create RTM client: $e');
    }
    ```

    #### Stream connection [#stream-connection-15]

    When you create a stream channel instance and successfully join a stream channel, the client sends heartbeat packets to the server at 0.5 second intervals to keep the connection active. The stream connection heartbeat interval cannot be changed. For application use-cases that require increased battery life, Agora does not recommend use of stream connections.

    ### Heartbeat interval and presence timeout parameters [#heartbeat-interval-and-presence-timeout-parameters-6]

    `RtmConfig` includes two time interval parameters: `heartbeatInterval` and `presenceTimeout`. This section explains the two parameters and their relationship, to enable you to configure the Signaling client more effectively.

    1. `heartbeatInterval`: This parameter determines how often the client sends ping packets to the server to maintain an active connection. It affects the PCU count and is crucial for the SDK's global connection management functionality.

    2. `presenceTimeout`: If the client's ping packet is not received within the set `heartbeatInterval` plus a 10-second redundancy period, the server considers it a possible network connection failure. To account for the possibility that the client may be trying to fix the problem, the server delays broadcasting event notifications to other users in the channel for a period of time defined by the `presenceTimeout`. This approach helps avoid repeated notification of events as follows:

       * If the client successfully reconnects within the `presenceTimeout` period, the server does not send event notifications to other users, and the temporary user status set by the client is retained.

       * If the client fails to reconnect within the `presenceTimeout` period, the server broadcasts an `presence` event notification with `remoteTimeout` to other users in the channel and clears the client's temporary user status. When the client successfully reconnects and resumes its subscription to the channel, the server broadcasts `remoteJoinChannel` event notifications to other users in the channel. If the client had previously set a temporary user state, it reapplies the cached temporary user state from the local session. Other users in the channel receive a corresponding `remoteStateChanged` event notification.

    For local users, departures triggered by presence timeout and departures resulting from calling `unsubscribe` are both considered channel leaving behaviors. The difference lies in the fact that presence timeout departures are typically caused by network connection failures. The local user may be in a `disconnected` or `suspended` state and attempting to reconnect. If the reconnection is successful, the channel subscription relationship and temporary user status are automatically restored. For other users in the channel, the user is identified as a rejoined user. An `unsubscribe` call is considered as a user actively leaving a channel. It prompts the client to clear the subscription relationship and the temporary user status for this channel.

    For example, suppose Client A sets the `heartbeatInterval` to 10 seconds and the `presenceTimeout` to 5 seconds. If Client A sends a ping packet but fails to receive a pong packet within 10 seconds, its connection state changes to `disconnected`. As Client A attempts to reconnect, the server waits for up to 25 seconds. If Client A fails to reconnect within this time, the server broadcasts an `presence` notification of type `remoteTimeout` to other users in the channel. If Client A successfully restores the connection within 25 seconds, the server does not broadcast event notifications, and other users in the channel consider Client A to have never left the channel. In this example, it took the `heartbeatInterval` of 10 seconds, plus an error range of 10 seconds to allow for network delays, plus a `presenceTimeout` interval of 5 seconds from when Client A dropped offline to when other users were notified. The total time interval was 25 seconds.

    The `presenceTimeout` is crucial for handling situations where the network connection is quickly restored after being disconnected, such as network switching or driving through a tunnel. It prevents excessive event notifications and improves the user experience.

    ### Close the connection [#close-the-connection-4]

    When a connection between the client and server is no longer required, call an appropriate method to close the connection.

    #### Message connection [#message-connection-14]

    In a message channel, the connection status affects measurement of the peak number of connections. Best practice is to actively disconnect by calling the `logout` method to log out of Signaling.

    ```dart
    try {
        var (status, response) = await rtmClient.logout();
        if (status.error == true ){
           print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
        } else {
            print('${status.operation} success!');
        }
    } catch (e) {
        print('something went wrong: $e');
    }
    ```

    <CalloutContainer type="info">
      <CalloutDescription>
        When you call the `logout` method to disconnect, both `MESSAGE` and `STREAM` connections are terminated simultaneously. You exit all channels, and all cached data in the client is cleared.
      </CalloutDescription>
    </CalloutContainer>

    #### Stream connection [#stream-connection-16]

    When you no longer need a stream connection, call the `leave` method to exit the channel and disconnect the stream connection.

    ```dart
    try {
        var (status, response) = await stChannel.leave();
        if (status.error == true ){
           print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
        } else {
            print('${status.operation} success!');
        }
    } catch (e) {
        print('something went wrong: $e');
    }
    ```

    
  
      
  
      
  
