Signatur
Beschreibung
RTCSctpTransport steht für die SCTP-Verbindung (Stream Control Transmission Protocol), die WebRTC für Datenkanäle nutzt. Alle RTCDataChannel-Objekte einer RTCPeerConnection teilen sich eine SCTP-Verbindung. Diese läuft ihrerseits verschlüsselt über einen RTCDtlsTransport.
Du kannst das Objekt nicht selbst erzeugen, es hat keinen Konstruktor. Du erreichst es über RTCPeerConnection.sctp. Die Eigenschaft ist null, bis SCTP ausgehandelt wurde. Dafür muss mindestens ein Datenkanal angelegt sein und die Remote-Beschreibung mit einem m=application-Abschnitt gesetzt worden sein.
Die Schnittstelle bietet diese schreibgeschützten Eigenschaften:
state: Zustand der Verbindung, also"connecting","connected"oder"closed".maxMessageSize: größte Nachricht in Bytes, dieRTCDataChannel.send()annimmt. Der Wert wird mit der Gegenseite ausgehandelt und kannInfinitysein.maxChannels: Höchstzahl gleichzeitig offener Datenkanäle. Vor dem Zustand"connected"ist der Wertnull.transport: der zugrunde liegendeRTCDtlsTransport.
Ändert sich state, wird das Ereignis statechange ausgelöst. Du kannst es mit addEventListener("statechange", …) oder über die Eigenschaft onstatechange abfangen.
Wofür du das in der Praxis brauchst:
- große Dateien anhand von
maxMessageSizein passende Teile zerlegen, - die Verbindungsqualität überwachen, über
transport.iceTransport, - Diagnose, wenn Datenkanäle nicht aufgehen.
Rückgabewert
RTCPeerConnection.sctp. Vor der SCTP-Aushandlung ist der Wert null.Beispiele
SCTP-Transport lokal aushandeln und auslesen
// Zwei Peers im selben Tab (Loopback), um SCTP ohne Signalisierungsserver zu testen
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
pc1.onicecandidate = (e) => e.candidate && pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = (e) => e.candidate && pc1.addIceCandidate(e.candidate);
// Ohne Datenkanal wird kein SCTP ausgehandelt
const channel = pc1.createDataChannel('chat');
console.log('Vor Aushandlung:', pc1.sctp);
const offer = await pc1.createOffer();
await pc1.setLocalDescription(offer);
await pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
await pc2.setLocalDescription(answer);
await pc1.setRemoteDescription(answer);
const sctp = pc1.sctp;
console.log('Zustand:', sctp.state);
console.log('Max. Nachrichtengröße:', sctp.maxMessageSize);
console.log('DTLS-Zustand:', sctp.transport.state);
Auf Zustandsänderungen reagieren (addEventListener und onstatechange)
const watchSctp = (pc) => {
const sctp = pc.sctp;
if (!sctp) return;
const onChange = () => {
console.log('SCTP-Zustand:', sctp.state);
if (sctp.state === 'connected') {
console.log('Max. Kanäle:', sctp.maxChannels);
}
if (sctp.state === 'closed') {
// Listener wieder entfernen, wenn die Verbindung beendet ist
sctp.removeEventListener('statechange', onChange);
}
};
sctp.addEventListener('statechange', onChange);
// Alternative mit der Eigenschaft:
// sctp.onstatechange = onChange;
};
// Aufruf nach setRemoteDescription():
// watchSctp(pc1);
Datei passend zu maxMessageSize aufteilen
const sendFile = async (pc, channel, file) => {
// Konservativer Standardwert, falls noch nichts ausgehandelt wurde
const max = pc.sctp?.maxMessageSize ?? 16 * 1024;
// Nicht zu große Teile wählen, damit der Kanal nicht blockiert
const chunkSize = Math.min(max, 64 * 1024);
const buffer = await file.arrayBuffer();
channel.bufferedAmountLowThreshold = chunkSize * 4;
for (let offset = 0; offset < buffer.byteLength; offset += chunkSize) {
if (channel.bufferedAmount > chunkSize * 16) {
await new Promise((r) =>
channel.addEventListener('bufferedamountlow', r, { once: true })
);
}
channel.send(buffer.slice(offset, offset + chunkSize));
}
console.log(`Gesendet: ${buffer.byteLength} Bytes in Teilen zu ${chunkSize} Bytes`);
};
// Wichtig · Fallstricke
pc.sctpist oftnull: SCTP gibt es erst, nachdem vor dem Angebot mindestens ein Datenkanal angelegt und die Remote-Beschreibung gesetzt wurde. Prüfe deshalb immer mitpc.sctp?.…. Eine reine Audio- oder Video-Verbindung hat keinen SCTP-Transport.maxMessageSizeist nicht einheitlich: Je nach Browser und Gegenseite liegt der Wert z. B. bei 64 KiB, 256 KiB oder 1 GiB. Größere Nachrichten lassensend()mit einemTypeErrorscheitern. Zerlege Daten daher immer in Teile.maxChannelsist erst im Zustand"connected"gesetzt, vorher ist der Wertnull.- Browser-Unterstützung: Chrome/Edge ab 76, Firefox ab 64, Safari erst ab 15.4. In älteren Safari-Versionen fehlt
RTCPeerConnection.sctpganz. Prüfe das per Feature-Erkennung:'sctp' in RTCPeerConnection.prototype. - Du kannst das Objekt nicht selbst mit
newerzeugen. Der Browser verwaltet es, und nachpc.close()wechselt es in den Zustand"closed".