Levenscyclus en herverbinding van een verbinding
Een Realtime-verbinding is één WebSocket. Netwerkwijzigingen, slapende apparaten en herstarts van infrastructuur kunnen hem sluiten. De client verbindt automatisch opnieuw, terwijl je app de huidige verbindingstoestand kan tonen.
De zes toestanden
bird.connection.state in de browserclient en bird.connectionState in Swift en Kotlin is altijd een van deze (Kotlin schrijft ze als ConnectionState-constanten, dus unavailable wordt ConnectionState.UNAVAILABLE):
| Toestand | Betekenis |
|---|---|
| initialized | De client bestaat en heeft nog geen socket geopend. |
| connecting | Een socket wordt geopend, of is open en wacht op de handshake. |
| connected | De handshake is ontvangen. De verbinding heeft een ID en kan subscriben. |
| unavailable | De verbinding is weggevallen en een herverbinding is ingepland. |
| disconnected | Je hebt disconnect() aangeroepen. Er is niets ingepland. |
| failed | De server heeft deze verbinding geweigerd. De client probeert het niet opnieuw. |
Bind state_change om elke overgang te zien, of bind een enkele toestandsnaam als er maar één relevant is:
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 en Kotlin gebruiken één observer voor elke overgang, dus branch op current. Handlers draaien op de main queue in Swift en op de Android main looper in Kotlin wanneer beschikbaar. Geef een deliveryQueue of Executor mee om een andere executiecontext te gebruiken.
Een open socket blijft in connecting totdat de handshake van de server binnenkomt. De handshake stelt bird.connection.connectionId in voordat de toestand connected wordt, zodat autorisatie dat ID kan ondertekenen. Als de handshake het ID weglaat, meldt de client een fout en sluit de socket.
Automatische herverbinding
Na een onverwachte onderbreking wacht de client voordat hij een nieuwe socket opent. De vertraging gebruikt full-jitter exponential backoff met een basis van één seconde en een maximum van 30 seconden. Elke geslaagde handshake reset de backoff.
De close-code bepaalt welk van drie dingen er gebeurt:
| Close-code | Gedrag |
|---|---|
| 4000 tot 4099 | Geweigerd. Geen retry, toestand gaat naar failed. |
| 4200 tot 4299 | Direct opnieuw proberen. |
| Al het andere | Toestand gaat naar unavailable, daarna opnieuw proberen met backoff. |
Netwerkfouten volgen het backoff-pad. Verwerk weigeringscodes in je UI, want deze definitieve fouten verbinden niet automatisch opnieuw.
De controle op inactieve verbindingen
Een socket kan open lijken nadat het netwerkpad is uitgevallen. De client stuurt een ping na de activiteits-timeout, die standaard 120 seconden is tenzij de handshake een andere waarde meegeeft. Als er geen pong binnenkomt binnen de standaard pong-timeout van 30 seconden, sluit de client de socket met een direct-opnieuw-proberen-code.
Wat er met je channels gebeurt
Subscriptions horen bij de verbinding, dus een onderbreking verwijdert ze. De client behoudt elk channel-object, subscribet opnieuw na de volgende connected-toestand en behoudt de bestaande handlers.
De client roept je authEndpoint opnieuw aan voor elk private en presence channel met het nieuwe connection-ID. De oude handtekening kan niet hergebruikt worden omdat die het vorige connection-ID bevat. Na één signin()-aanroep logt de client ook in op elke nieuwe verbinding en meldt latere fouten via 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}")
}Terwijl een channel opnieuw verbindt, geeft channel.trigger false terug zonder het client event te versturen. Controleer channel.subscribed, of verstuur na bird:subscription_succeeded, dat na elke geslaagde hersubscriptie wordt afgevuurd.
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 speelt geen events af die gepubliceerd zijn terwijl een client niet verbonden was. Als een weergave na een onderbreking moet herstellen, haal je de huidige toestand op bij bird:subscription_succeeded en pas je latere events vanaf dat punt toe.
Bewust de verbinding verbreken
bird.disconnect() sluit de socket zonder een herverbinding in te plannen. Gebruik het wanneer een uitgelogde of inactieve client geen live data meer nodig heeft. De client behoudt channels, dus een latere bird.connect() opent de socket opnieuw en subscribet opnieuw.
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-subscribesOp mobiel verbreek je de verbinding wanneer de relevante view of activity stopt, en verbind je opnieuw wanneer die hervat. Channel-objecten en bindings blijven beschikbaar.
Fouten op de verbinding versus fouten op een channel
Serverfouten die bij één channel horen, komen op dat channel binnen. Een geweigerde subscription is de meest voorkomende, en een authorizer die 403 teruggeeft verschijnt hier:
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")
}Alles wat de verbinding niet aan een channel toeschrijft, komt in plaats daarvan op de verbinding binnen:
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}")
}Close-code 4009 afhandelen
Code 4009 valt in de no-retry-band, dus de verbinding gaat naar failed. Controleer de reden om deze situaties te onderscheiden:
- Een beëindigd lid. Je backend heeft de disconnect API voor dit lid aangeroepen, waardoor elke verbinding die het had is gesloten. Zie Lidverbindingen beëindigen.
- Een verbinding die nooit heeft geautoriseerd. De app vereist geautoriseerde verbindingen en deze heeft niet op tijd geautoriseerd. Zie Geautoriseerde verbindingen vereisen.
De client verbindt niet automatisch opnieuw, dus je app bepaalt wat er vervolgens gebeurt:
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()
}Een uitgelogde toestand is passend wanneer authenticatie is beëindigd. bird.connect() aanroepen start een nieuwe verbinding en herhaalt de autorisatie, dus verbind pas opnieuw nadat de autorisatietoestand van de aanroeper verandert.
Volgende stappen
- Channels autoriseren is het contract dat je backend implementeert, en het verzoek dat de client bij elke herverbinding herhaalt.
- Geautoriseerde verbindingen vereisen maakt van een niet-geautoriseerde verbinding een gesloten verbinding.
- Lidverbindingen beëindigen is hoe een verbinding bewust met 4009 wordt gesloten.
- Realtime-overzicht behandelt channels, leden en verbindingen als model.
Gerelateerde bronnen
Ga verder met de documentatie, gidsen en voorbeelden voor dit onderwerp. De bronnen zijn in het Engels.
Ontdek de mogelijkheidRealtimeVolg het leerpadBuild your first integrationImplementatiegidsSend your first realtime event
Probeer de oefening en ontvang een implementatieoverzicht