Signatur
Beschreibung
Die schreibgeschützte Eigenschaft requestsReceived des Wörterbuchs RTCIceCandidatePairStats enthält eine ganze Zahl. Sie gibt an, wie viele STUN-Konnektivitätsprüfanfragen (Connectivity Checks) bisher auf der Verbindung eingegangen sind, die durch dieses Paar aus lokalem und entferntem ICE-Kandidaten beschrieben wird.
Solche Statistikobjekte bekommt man über RTCPeerConnection.getStats(). Das zurückgegebene RTCStatsReport enthält Einträge mit type === "candidate-pair". Die Eigenschaft hilft vor allem bei der Fehlersuche im ICE-Verbindungsaufbau: Bleibt requestsReceived bei 0, während requestsSent steigt, erreichen die Prüfungen der Gegenstelle diesen Kandidaten nicht. Häufige Ursachen sind eine Firewall, NAT oder ein fehlender TURN-Server.
Der Zähler bezieht sich nur auf eingehende Anfragen. Antworten darauf werden getrennt gezählt, und zwar in responsesSent und responsesReceived. Auch Consent-Freshness-Prüfungen nach RFC 7675 zählen mit. Deshalb steigt der Wert bei einer bestehenden Verbindung regelmäßig weiter an.
Rückgabewert
unsigned long long) mit der Gesamtzahl der bisher empfangenen STUN-Konnektivitätsprüfanfragen für dieses Kandidatenpaar.Beispiele
Empfangene Prüfanfragen aller Kandidatenpaare auslesen
const logCandidatePairs = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === "candidate-pair") {
console.log(`${stats.id}: ${stats.state}, empfangen: ${stats.requestsReceived}, gesendet: ${stats.requestsSent}`);
}
});
};
// pc ist eine bestehende RTCPeerConnection
await logCandidatePairs(pc);
Einseitige Konnektivität erkennen (Firewall-Diagnose)
const diagnoseIce = async (pc) => {
const report = await pc.getStats();
for (const stats of report.values()) {
if (stats.type !== "candidate-pair") continue;
const { requestsSent = 0, requestsReceived = 0 } = stats;
if (requestsSent > 5 && requestsReceived === 0) {
const local = report.get(stats.localCandidateId);
const remote = report.get(stats.remoteCandidateId);
console.warn(
`Keine eingehenden Prüfungen: ${local?.candidateType} -> ${remote?.candidateType}. ` +
"Evtl. blockiert eine Firewall – TURN-Server prüfen."
);
}
}
};
pc.addEventListener("iceconnectionstatechange", () => {
if (pc.iceConnectionState === "failed") diagnoseIce(pc);
});
Aktives Paar regelmäßig überwachen
const monitorSelectedPair = (pc, intervalMs = 5000) => {
let last = 0;
const timer = setInterval(async () => {
const report = await pc.getStats();
const transport = [...report.values()].find((s) => s.type === "transport");
const pair = transport && report.get(transport.selectedCandidatePairId);
if (!pair) return;
const delta = pair.requestsReceived - last;
last = pair.requestsReceived;
console.log(`Neue Prüfanfragen im Intervall: ${delta}`);
}, intervalMs);
return () => clearInterval(timer);
};
const stop = monitorSelectedPair(pc);
// später: stop();
// Wichtig · Fallstricke
- Nicht mit Antworten verwechseln:
requestsReceivedzählt nur eingehende Anfragen. Ob Prüfungen erfolgreich waren, zeigenresponsesReceivedundresponsesSent. - Der Zähler kann ganz fehlen, wenn ein Browser ihn nicht unterstützt. Deshalb mit einem Standardwert absichern, z. B.
stats.requestsReceived ?? 0. - Der Wert kann den Wert von
requestsSentübersteigen. Der Grund sind Wiederholungen und Consent-Freshness-Prüfungen der Gegenstelle. Ein Ungleichgewicht allein bedeutet also keinen Fehler. - Die Browser-Unterstützung für einzelne Statistikfelder unterscheidet sich. Ältere Safari- und Firefox-Versionen liefern nicht alle Zähler von
candidate-pair. Vor dem Einsatz in Produktion sollte man daher auf die Kompatibilitätstabellen schauen. getStats()in kurzen Abständen aufzurufen kostet Rechenzeit. Für die Überwachung genügen Intervalle von einer Sekunde oder mehr.