Ciclo di vita della connessione e riconnessione
Una connessione Realtime è un singolo WebSocket. Cambi di rete, dispositivi in sospensione e riavvii dell'infrastruttura possono chiuderla. Il client si riconnette automaticamente, mentre la tua app può mostrare lo stato corrente della connessione.
I sei stati
bird.connection.state nel client browser, e bird.connectionState in Swift e Kotlin, è sempre uno di questi (Kotlin li rappresenta come costanti ConnectionState, quindi unavailable diventa ConnectionState.UNAVAILABLE):
| Stato | Significato |
|---|---|
| initialized | Il client esiste e non ha ancora aperto un socket. |
| connecting | Un socket si sta aprendo, oppure è aperto e in attesa dell'handshake. |
| connected | L'handshake è andato a buon fine. La connessione ha un ID e può sottoscrivere. |
| unavailable | La connessione è caduta e una riconnessione è pianificata. |
| disconnected | Hai chiamato disconnect(). Nessuna operazione è pianificata. |
| failed | Il server ha rifiutato questa connessione. Il client non riprova. |
Associa state_change per vedere ogni transizione, oppure associa un singolo nome di stato quando ne interessa solo uno:
import { BirdRealtime } from "@messagebird/realtime";
const bird = new BirdRealtime({ appKey: "your-app-key", region: "us1" });
bird.connection.bind("state_change", ({ previous, current }) => {
console.log(previous, "->", current);
});
bird.connection.bind("unavailable", () => showReconnectingBanner());
bird.connection.bind("connected", () => hideReconnectingBanner());import BirdRealtime
let bird = BirdRealtime(options: .init(appKey: "your-app-key", region: "us1"))
bird.onConnectionStateChange { previous, current in
print(previous, "->", current)
if current == .unavailable { showReconnectingBanner() }
if current == .connected { hideReconnectingBanner() }
}import com.bird.realtime.BirdRealtime
import com.bird.realtime.BirdRealtimeOptions
import com.bird.realtime.ConnectionState
val bird = BirdRealtime(BirdRealtimeOptions(appKey = "your-app-key", region = "us1"))
bird.onConnectionStateChange { previous, current ->
println("$previous -> $current")
if (current == ConnectionState.UNAVAILABLE) showReconnectingBanner()
if (current == ConnectionState.CONNECTED) hideReconnectingBanner()
}Swift e Kotlin usano un unico observer per ogni transizione, quindi gestisci i casi su current. Gli handler vengono eseguiti sulla main queue in Swift e sul main looper Android in Kotlin, quando disponibile. Passa un deliveryQueue o Executor per usare un altro contesto di esecuzione.
Un socket aperto resta in connecting finché non arriva l'handshake del server. L'handshake imposta bird.connection.connectionId prima che lo stato diventi connected, così l'autorizzazione può firmare quell'ID. Se l'handshake non include l'ID, il client segnala un errore e chiude il socket.
Riconnessione automatica
Dopo un'interruzione imprevista, il client attende prima di aprire un nuovo socket. Il ritardo usa un backoff esponenziale con full jitter, base di un secondo e tetto di 30 secondi. Ogni handshake riuscito azzera il backoff.
Il close code determina quale delle tre situazioni si verifica:
| Close code | Comportamento |
|---|---|
| 4000 a 4099 | Rifiutato. Nessun tentativo, lo stato passa a failed. |
| 4200 a 4299 | Riconnessione immediata. |
| Tutti gli altri | Lo stato passa a unavailable, poi riconnessione con backoff. |
I problemi di rete seguono il percorso con backoff. Gestisci i codici di rifiuto nella tua UI perché questi errori terminali non si riconnettono automaticamente.
Il controllo di connessione inattiva
Un socket può risultare aperto dopo che il suo percorso di rete è caduto. Il client invia un ping dopo il timeout di attività, che per default è 120 secondi a meno che l'handshake non fornisca un altro valore. Se nessun pong arriva entro il timeout pong predefinito di 30 secondi, il client chiude il socket con un codice di riconnessione immediata.
Cosa succede ai tuoi canali
Le sottoscrizioni appartengono alla connessione, quindi un'interruzione le rimuove. Il client mantiene ogni oggetto canale, si risottoscrive dopo il successivo stato connected e conserva gli handler esistenti.
Il client chiama di nuovo il tuo authEndpoint per ogni canale privato e di presenza usando il nuovo ID di connessione. Non può riutilizzare la vecchia firma perché quella firma include l'ID di connessione precedente. Dopo una chiamata signin(), il client esegue anche il sign-in su ogni nuova connessione e segnala eventuali errori successivi tramite signin_error.
bird.connection.bind("signin_error", ({ message }) => {
console.warn("connection has no identity:", message);
});bird.onSigninError { error in
print("connection has no identity:", error.message)
}bird.onSigninError { error ->
println("connection has no identity: ${error.message}")
}Mentre un canale si sta riconnettendo, channel.trigger restituisce false senza inviare l'evento client. Controlla channel.subscribed, oppure invia dopo bird:subscription_succeeded, che si attiva dopo ogni risottoscrizione riuscita.
const room = bird.subscribe("presence-room-1");
room.bind("bird:subscription_succeeded", ({ members }) => {
renderMembers(members);
});guard let room = bird.subscribe("presence-room-1") as? PresenceChannel else { return }
room.bind(BirdProtocol.Event.subscriptionSucceeded) { _ in
renderMembers(room.members)
}val room = bird.subscribe("presence-room-1")
if (room is PresenceChannel) {
room.bind(BirdProtocol.Event.SUBSCRIPTION_SUCCEEDED) {
renderMembers(room.members)
}
}Realtime non riproduce gli eventi pubblicati mentre un client è disconnesso. Se una vista deve recuperare dopo un'interruzione, recupera il suo stato corrente su bird:subscription_succeeded e applica gli eventi successivi da quel punto.
Disconnessione volontaria
bird.disconnect() chiude il socket senza pianificare una riconnessione. Usalo quando un client disconnesso o inattivo non ha più bisogno di dati in tempo reale. Il client mantiene i canali, quindi un successivo bird.connect() riapre il socket e risottoscrive.
bird.disconnect(); // state: disconnected, no reconnect
bird.connect(); // reopens and re-subscribesbird.disconnect() // state: disconnected, no reconnect
bird.connect() // reopens and re-subscribesbird.disconnect() // state: DISCONNECTED, no reconnect
bird.connect() // reopens and re-subscribesSu mobile, disconnetti quando la vista o l'activity pertinente si ferma e riconnetti quando riprende. Gli oggetti canale e i binding restano disponibili.
Errori sulla connessione ed errori su un canale
Gli errori del server che appartengono a un canale arrivano su quel canale. Una sottoscrizione rifiutata è il caso più comune, e un authorizer che restituisce 403 compare qui:
room.bind("bird:subscription_error", (err) => {
console.warn("could not join:", err);
});room.bind(BirdProtocol.Event.subscriptionError) { error in
print("could not join:", error ?? "")
}room.bind(BirdProtocol.Event.SUBSCRIPTION_ERROR) { error ->
println("could not join: $error")
}Tutto ciò che il protocollo non attribuisce a un canale arriva invece sulla connessione:
bird.connection.bind("error", ({ code, message }) => {
console.warn(code, message);
});bird.onError { error in
print(error.code ?? 0, error.message)
}bird.onError { error ->
println("${error.code} ${error.message}")
}Gestire il close code 4009
Il codice 4009 rientra nella fascia senza ripetizione, quindi la connessione entra in failed. Controlla il motivo per distinguere queste situazioni:
- Un membro terminato. Il tuo backend ha chiamato API di disconnessione per questo membro, quindi ogni connessione che detiene è stata chiusa. Vedi Terminare le connessioni dei membri.
- Una connessione mai autorizzata. L'app richiede connessioni autorizzate e questa non si è autorizzata in tempo. Vedi Richiedere connessioni autorizzate.
Il client non si riconnette automaticamente, quindi la tua app decide cosa fare:
bird.connection.bind("error", ({ code }) => {
if (code === 4009) showSignedOutScreen();
});bird.onError { error in
if error.code == 4009 { showSignedOutScreen() }
}bird.onError { error ->
if (error.code == 4009) showSignedOutScreen()
}Uno stato di disconnessione è appropriato quando l'autenticazione è terminata. Chiamare bird.connect() avvia una nuova connessione e ripete l'autorizzazione, quindi riconnetti solo dopo che lo stato di autorizzazione del chiamante cambia.
Prossimi passi
- Autorizzazione dei canali è il contratto implementato dal tuo backend, e la richiesta che il client ripete a ogni riconnessione.
- Richiedere connessioni autorizzate trasforma una connessione non autorizzata in una connessione chiusa.
- Terminare le connessioni dei membri è il modo in cui una connessione viene chiusa con 4009 intenzionalmente.
- Panoramica di Realtime copre canali, membri e connessioni come modello.
Risorse correlate
Prosegui con la documentazione, le guide e gli esempi per questo argomento. Le risorse sono in inglese.
Esplora la funzionalitàRealtimeSegui il percorso di apprendimentoBuild your first integrationGuida all'implementazioneSend your first realtime event
Prova l'esercitazione e ottieni un brief di implementazione