WebRTC
Peer-to-peer соединение между браузерами: видео, аудио, произвольные данные через
RTCDataChannel.
Что это
Real-Time Communication. Прямое UDP-соединение между двумя клиентами в обход сервера для самой передачи (сервер нужен только для discovery — сигнальный сервер). Три кита: RTCPeerConnection (само соединение), MediaStream (медиа из камеры/микрофона через getUserMedia), RTCDataChannel (произвольные данные).
Базовое использование
// 1. Создаём peer connection с STUN-серверами (для обнаружения внешнего IP)
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
],
});
// 2. DataChannel (например для чата) — инициатор создаёт
const channel = pc.createDataChannel('chat');
channel.onmessage = (e) => console.log('peer:', e.data);
channel.onopen = () => channel.send('hello');
// 3. ICE-кандидаты (адреса) — отдаём другой стороне через сигнальный сервер
pc.onicecandidate = (e) => {
if (e.candidate) signaling.send({ type: 'ice', candidate: e.candidate });
};
// 4. SDP-offer создаёт инициатор
const offer = await pc.createOffer;
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: offer });
// На стороне ответчика:
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer;
await pc.setLocalDescription(answer);
signaling.send({ type: 'answer', sdp: answer });
// Обратно на стороне инициатора:
await pc.setRemoteDescription(answer);
// Обмен ICE-кандидатами по пути:
pc.addIceCandidate(candidateFromPeer);
// 5. После handshake — channel открыт, можно отправлять
channel.send('текст');
channel.send(new Uint8Array([1, 2, 3]));
Медиа (видеозвонок)
const stream = await navigator.mediaDevices.getUserMedia({
video: true, audio: true,
});
stream.getTracks.forEach((track) => pc.addTrack(track, stream));
pc.ontrack = (e) => {
remoteVideo.srcObject = e.streams[0];
};
Архитектура
[Browser A] ──signaling (WS/HTTP)── [Signaling Server] ──signaling── [Browser B]
│ │
└──────────── ICE/STUN handshake через STUN server ──────────────────┘
│ │
└──────── P2P data/media (UDP, прямой канал) ────────────────────────┘
- Signaling server — твой код (WebSocket-сервер), который пересылает SDP offer/answer и ICE-кандидатов между пирами
- STUN server — узнаёт публичный IP клиента за NAT (
stun.l.google.com:19302— public Google) - TURN server — relay-сервер для случаев когда NAT непрорывается (коммерческий, дорого)
Поддержка
Все современные браузеры. На iOS Safari — есть, с особенностями (медиа-разрешения).
Подводные камни
- Сигналинг нужен ВСЕГДА — без сервера для обмена SDP пиры не найдут друг друга
- ICE-handshake может занять секунды
- За симметричным NAT (корпоративные сети) без TURN не пробьёшься
- DataChannel ordered/reliable по умолчанию — настраивается через опции в
createDataChannel - Большие файлы лучше резать на чанки (~16KB) — иначе
bufferedAmountзабивает - В одном
RTCPeerConnectionможет быть многоDataChannel'ов
Используется в bootcamp
- Не в текущих задачах bootcamp напрямую, но один из главных Web API для real-time приложений (P2P чаты, видеозвонки, multiplayer games)
Ссылки
🎓 Источники
- 🎓 💬 WebRTC для создания P2P чата: Node.js STUN, сигнальный сервер, WebRTC чат клиента · TimurShemsedinov · 2025-12-12
- Архитектура: signaling-сервер (HTTP) + STUN-сервер (UDP, Node.js
dgram) + клиент. - Создание
RTCPeerConnection({ iceServers: [...] }), обмен SDP-offer/answer. - ICE-кандидаты — пары IP+порт; после обмена открывается UDP-канал.
dataChannel.send(text)уходит по UDP через WebRTC, не через сервер.
- Архитектура: signaling-сервер (HTTP) + STUN-сервер (UDP, Node.js
- 🎓 🔀 Фронтендеры не знают Web API · TimurShemsedinov · 2025-12-10