Synchronisierung mehrerer Geräte (Mobiltelefone) – React Native
P粉151466081
2023-09-05 11:58:38
<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>
你想做的事情真的很难。同步这样的设备很困难。当您不拥有和控制硬件时,这样做几乎是不可能的。坦率地说,我认为你永远不会得到你想要的。
时间戳永远不会起作用。其一,这些设备不会都有相同的时间。他们都会稍微偏离。您的下一个想法是从中央源(例如您的服务器)向他们发送时间。问题在于,向每个设备发送数据将花费不同的、随机的时间。您可以尝试通过预先计算十几个数据包的往返时间来猜测延迟,但这仍然是一个猜测,对于下一个数据包可能不准确。 NTP 有助于使设备的时间接近同一时间,但没有达到您想要的精度。
即使它确实达到了您想要的准确性 - Android 也不是实时操作系统。 iPhone 则不然。即使您将闹钟设置为 12:00:00,它也不会恰好在 12:00:00.000 触发。在那之后的一段时间,当操作系统有空闲时间、空闲核心并且认为您的应用程序是最重要的调度应用程序时,它将触发。这可能需要几百毫秒。有些操作系统可以给您带来您想要的承诺。它们被称为实时操作系统,通常用于不会出现故障的嵌入式设备,例如医疗设备和昂贵机器的控制器。它们是一种与消费设备使用的完全不同的操作系统编写方法。
我真的建议重新考虑您的需求并更加现实地对待它们。有些技术可以让您得到您想要的东西,但不能通过互联网在消费者操作系统上的随机硬件上获得。
另外,如果你想这样做 - 我真的不建议使用 React Native,它以垃圾收集语言运行解释器,并且具有非常随机的计时。您至少需要用 C 语言编写启动器,因为这是最可预测的方法。
但实际上,请重新考虑您的需求。为什么需要在 50 毫秒内启动?当您通过互联网做事时,如果人们有一秒钟不同步,这真的很重要吗?