Synchronisierung mehrerer Geräte (Mobiltelefone) – React Native
<p>Ich versuche, eine Lichtshow zu erstellen, die auf den Mobilgeräten aller Benutzer gleichzeitig startet (kann bis zu 2.000–3.000 Benutzer haben). Alle Benutzer nutzen das Internet (WLAN oder mobile Daten). In unserem FE verwenden wir Apollo für Abonnements und es funktioniert hervorragend. </p>
<p>Das Problem besteht jedoch darin, dass Benutzer A Abonnementereignisse schneller erhalten kann als Benutzer B. Das bedeutet, dass Benutzer A früher mit dem Spiel beginnt als Benutzer B, was ein Problem darstellt, da wir über eine Lightshow-Architektur verfügen und Benutzer nicht früher oder später beginnen können. Als Benutzer werden Sie den Unterschied sofort bemerken, und er sieht nicht gut aus. </p>
<p>Was ich sehe ist, dass der Latenzunterschied bis zu 300 ms betragen kann. Die Zeit zwischen Android (Xiaomi 9) und iOS (iPhone11) beträgt meist etwa 180 ms+-. Wenn wir zwei iOS-Geräte, iPhone 11 und iPhone 13, vergleichen, beträgt der Unterschied etwa 50-100 Millisekunden. Gibt es eine Möglichkeit, diesen Unterschied zu beseitigen oder ihn zumindest für alle Geräte auf 40–60 ms zu reduzieren? </p>
<p>Beginnend in BE senden wir die Serverzeit (utc+0) und die Lichtshow startet mit dem Zeitstempel => In FE habe ich 10 Sekunden hinzugefügt, um allen Geräten Zeit zu geben, die Funktion aufzulösen, also den Start ist Verzögerung-> „Zeitstempel + 10 Sekunden“.</p>
<p>In FE habe ich die Bibliothek „react-native-ntp-client“ verwendet, um auf allen Gerätetypen (iOS/Android, weil ich festgestellt habe, dass die Zeit für jedes Gerät leicht unterschiedlich ist) die gleiche Zeit zu erhalten. Anschließend berechne ich die Differenz zwischen „start“ und „ntpTime“ und stelle diese als Timeout für meine setTimeout-Funktion bereit, die den Start der Lichtshow auslöst. </p>
<p>Nachfolgend habe ich ein Beispiel dafür gegeben, wie ich den Bildschirm verwende, auf dem sich die Lichtshow befindet. </p>
<pre class="brush:php;toolbar:false;">dayjs aus 'dayjs' importieren;
ntpClient aus „react-native-ntp-client“ importieren;
export const LightshowScreen: React.FC<
LightshowScreenProps<'Lightshow'>
> = ({route}) =>
const {Daten, Laden} = useSubscription(JOIN_LIGHTSHOW_SUBSCRIPTION, {
Variablen: {lightshowId: route.params.lightshow.id},
});
useEffect(() => {
const getServerTime = async (lightshowStartAt: number) =>
// Start um 10 Sekunden verzögern, um genügend Zeit zum Beenden unserer Funktionen zu haben – lightshowStartAt ist der Zeitstempel von unserem Server
const lightshowStart = dayjs.unix(lightshowStartAt).add(10, 's');
ntpClient.getNetworkTime('time.cloudflare.com', 123, (error, date) => {
if (Fehler) {
console.error('Kann keine Verbindung herstellen', Fehler);
zurückkehren;
}
console.log('NTP client date - ', date); // Mo 08.07.2013 21:31:31 GMT+0200 (Paris, Madrid (heure d’été))
let ntpTime = dayjs(date);
// Differenz in ms
const diff = lightshowStart.diff(ntpTime);
// Nach diesem Timeout sollten alle Geräte gleichzeitig mit der Wiedergabe beginnen
setTimeout(() => {
lightshowStartHandler();
}, diff);
});
};
if (data && data?.joinLightshow.started) {
const lightshowData = data.lightshow;
getServerTime(lightshowData.startedAt);
}
}, [Daten]);
useEffect(() => {
if (data && data?.joinLightshow?.finished) {
lightshowFinishHandler();
}
}, [Daten]);
zurückkehren (
<View style={style.container}>
....
</Anzeigen>
);
};</pre>
<p>Vielen Dank für all Ihre Kommentare und Gedanken;)</p>