Signatur
Beschreibung
Die Eigenschaft packetsSent des Wörterbuchs RTCIceCandidatePairStats enthält eine ganze Zahl. Sie gibt an, wie viele Pakete bisher insgesamt über ein bestimmtes ICE-Kandidatenpaar, also die Verbindung aus lokalem und entferntem Kandidaten, gesendet wurden. Der Zähler steigt nur an und beginnt bei der Erstellung des Kandidatenpaars.
Die Werte bekommt man über RTCPeerConnection.getStats(). Der zurückgegebene RTCStatsReport enthält für jedes Kandidatenpaar einen Eintrag mit type === "candidate-pair". Weil es während der ICE-Aushandlung oft mehrere Paare gibt, sollte man gezielt das aktuell ausgewählte Paar auswerten. Dieses erkennt man über RTCTransportStats.selectedCandidatePairId oder, als Ausweichlösung, über nominated und state === "succeeded".
Typische Einsatzzwecke sind Diagnose und Überwachung. Man kann die Senderate in Paketen pro Sekunde berechnen, packetsSent mit packetsReceived der Gegenstelle vergleichen oder zusammen mit bytesSent die durchschnittliche Paketgröße ermitteln.
Rückgabewert
unsigned long long) mit der Gesamtzahl der gesendeten Pakete. Die Eigenschaft ist schreibgeschützt und kann fehlen (undefined), wenn der Browser sie nicht unterstützt.Beispiele
packetsSent aller Kandidatenpaare ausgeben
const logCandidatePairs = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === "candidate-pair") {
console.log(`${stats.id}: ${stats.packetsSent ?? "n/a"} Pakete gesendet (Status: ${stats.state})`);
}
});
};
// pc ist eine bestehende, verbundene RTCPeerConnection
await logCandidatePairs(pc);
Ausgewähltes Kandidatenpaar über den Transport ermitteln
const getSelectedPair = async (pc) => {
const report = await pc.getStats();
let pair;
report.forEach((s) => {
if (s.type === "transport" && s.selectedCandidatePairId) {
pair = report.get(s.selectedCandidatePairId);
}
});
// Ausweichlösung für Browser ohne selectedCandidatePairId
if (!pair) {
report.forEach((s) => {
if (s.type === "candidate-pair" && s.nominated && s.state === "succeeded") pair = s;
});
}
return pair;
};
const pair = await getSelectedPair(pc);
console.log("Gesendete Pakete:", pair?.packetsSent);
Senderate in Paketen pro Sekunde überwachen
let last = null;
const monitor = setInterval(async () => {
const report = await pc.getStats();
let pair;
report.forEach((s) => {
if (s.type === "transport" && s.selectedCandidatePairId) {
pair = report.get(s.selectedCandidatePairId);
}
});
if (!pair || pair.packetsSent === undefined) return;
if (last && last.id === pair.id) {
const seconds = (pair.timestamp - last.timestamp) / 1000;
const rate = (pair.packetsSent - last.packetsSent) / seconds;
const avgSize = pair.bytesSent / pair.packetsSent;
console.log(`${rate.toFixed(1)} Pakete/s, Ø ${avgSize.toFixed(0)} Byte/Paket`);
}
last = pair;
}, 1000);
// Später: clearInterval(monitor);
// Wichtig · Fallstricke
- Browser-Kompatibilität:
packetsSentundpacketsReceivedauf Kandidatenpaaren werden nicht von allen Browsern gleich unterstützt. Prüfe den Wert deshalb immer aufundefined, zum Beispiel mit?? 0, und nimm bei BedarfbytesSentoder dieoutbound-rtp-Statistiken zu Hilfe. - Richtiges Paar wählen: Ein Bericht kann viele Kandidatenpaare enthalten, darunter fehlgeschlagene oder wartende. Nur das ausgewählte Paar zeigt den tatsächlichen Datenverkehr.
- Paarwechsel: Bei einem ICE-Neustart oder Netzwechsel, etwa von WLAN zu Mobilfunk, kann ein neues Paar gewählt werden. Der Zähler beginnt dann von vorn. Vergleiche bei Ratenberechnungen deshalb immer auch die
id. - Zeitbasis: Für Raten sollte man
timestampaus dem Statistikobjekt nehmen, nichtDate.now(), weil die Werte zu einem bestimmten Zeitpunkt erfasst werden. - Nicht erfolgreich gesendete Pakete, zum Beispiel wegen Socket-Fehlern, werden gesondert in
packetsDiscardedOnSenderfasst. - Häufiges Aufrufen von
getStats()(öfter als etwa einmal pro Sekunde) kostet unnötig Rechenzeit.