Fundamentals 16 min read

Understanding WebRTC: Architecture, NAT Traversal, and a Complete Demo

This article explains WebRTC fundamentals, compares it with WebSocket, describes SDP, ICE, STUN/TURN NAT traversal, and provides full server‑side and client‑side JavaScript code to build a peer‑to‑peer video conferencing demo.

ByteDance ADFE Team
ByteDance ADFE Team
ByteDance ADFE Team
Understanding WebRTC: Architecture, NAT Traversal, and a Complete Demo

Keywords : NAT (Network Address Translation), STUN (Session Traversal Utilities for NAT), TURN (Traversal Using Relays around NAT), ICE (Interactive Connectivity Establishment), SDP (Session Description Protocol), WebRTC (Web Real‑Time Communications).

WebRTC is a real‑time communication technology that enables browsers to establish peer‑to‑peer connections for audio, video, or arbitrary data streams without an intermediate server; it must run over HTTPS.

WebRTC vs WebSocket

WebSocket provides full‑duplex communication between a browser and a web server.

WebRTC provides full‑duplex communication directly between two browsers.

WebSocket uses TCP, while WebRTC uses UDP.

WebSocket traffic always passes through a server; WebRTC traffic is direct, saving bandwidth.

WebSocket latency is higher; WebRTC latency is lower.

In practice, WebRTC often works together with WebSocket, where WebSocket is used only to exchange SDP and network information needed to set up the WebRTC connection.

Offer/Answer Exchange

Similar to TCP three‑way handshake, WebRTC requires an offer/answer exchange (at least four messages) to negotiate connection parameters. An example flow can be seen in the demo at https://nashaofu.github.io/webrtc-demo/socket.html .

After exchanging offers and answers, WebRTC attempts a direct connection using the peers' IP addresses and ports; this is where NAT traversal ("hole punching") occurs.

Signaling Server

Since WebRTC does not define a signaling mechanism, any channel (e.g., WebSocket, XMLHttpRequest) can be used to exchange tokens such as SDP and ICE candidates between peers.

Data Transmission Support

WebRTC supports audio/video streams and also arbitrary data via a bidirectional dataChannel . Example code for adding a video track:

const pc = new RTCPeerConnection();
navigator.getUserMedia({video: true}, stream => {
  // Add video tracks to the session
  stream.getTracks().forEach(track => pc.addTrack(track, stream));
  // Show local video
  $localVideo.srcObject = stream;
});

Example code for using a data channel to send text messages:

const pc = new RTCPeerConnection();
const dataChannel = pc.createDataChannel('chat');
pc.addEventListener('datachannel', event => {
  event.channel.addEventListener('message', e => console.log('message', e.message));
});
dataChannel.addEventListener('open', () => {
  dataChannel.send('Hi!');
});

Session Description Protocol (SDP)

Offers and answers contain SDP text that describes media capabilities, codecs, bandwidth, and transport details. An SDP object looks like:

{
  type: "offer" | "answer",
  sdp: string
}

A typical SDP snippet includes version, origin, session name, connection data, and media announcements (audio, video, etc.).

ICE Candidate Event

When RTCPeerConnection.setLocalDescription() is called, the browser gathers local network candidates and emits a candidate event containing IP address, port, candidate type (host, srflx, relay), priority, and protocol.

{
  "address": "192.168.31.67",
  "candidate": "candidate:2147606101 1 udp 2122260223 192.168.31.67 57959 typ host ...",
  "component": "rtp",
  "foundation": "2147606101",
  "port": 57959,
  "priority": 2122260223,
  "protocol": "udp",
  "type": "host",
  "usernameFragment": "EaWw"
}

Candidate types:

host : address from the local network interface.

srflx : server‑reflexive address returned by a STUN server.

relay : relayed address allocated by a TURN server.

Network Address Translation (NAT)

NAT rewrites source or destination IP addresses and ports as packets pass through a router or firewall, allowing many private devices to share a single public IP address. NAT maintains a mapping table of internal IP:port ↔ external IP:port.

Different NAT types (full‑cone, restricted‑cone, port‑restricted, symmetric) affect the success of peer‑to‑peer connections.

NAT Traversal (Hole Punching)

WebRTC implements NAT hole punching automatically using ICE, which combines STUN (to discover public IP/port) and TURN (to relay traffic when direct connection fails). If hole punching fails, TURN is used as a fallback.

Demo Implementation

Signaling server (Node.js + socket.io) :

const socket = require('socket.io');
module.exports = server => {
  const io = socket.listen(server);
  io.sockets.on('connection', function(socket) {
    socket.on('disconnecting', () => {
      Object.keys(socket.rooms).forEach(room => {
        socket.broadcast.to(room).emit('leaveed', socket.id);
      });
    });
    socket.on('message', function(target, message) {
      if (target) {
        io.sockets.sockets[target]?.emit('message', message);
      }
    });
    socket.on('create or join', function(room) {
      const clientsInRoom = io.sockets.adapter.rooms[room];
      const numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;
      if (numClients === 0) {
        socket.join(room);
        socket.emit('created', room, socket.id);
      } else if (numClients < 10) {
        socket.join(room);
        socket.emit('joined', room, socket.id);
        socket.broadcast.to(room).emit('message', {socketId: socket.id, type: 'join'});
      } else {
        socket.emit('full', room);
      }
    });
  });
};

Client side (browser JavaScript) creates a RTCPeerConnection , obtains local media, handles ICE candidates, and processes signaling messages (join, offer, answer, candidate). The code also manages room creation/joining, video element insertion, and cleanup when peers leave.

const videos = document.querySelector('#videos');
const localVideo = document.querySelector('#localVideo');
const socket = io.connect();
// ... getUserMedia, createRTC, sendMsg, handle 'message' events, etc.

Full source code and additional examples are available at https://github.com/nashaofu/webrtc-demo .

Images illustrating NAT mapping, ICE flow, and the demo UI are included in the original article.

JavaScriptWebSocketreal-time communicationWebRTCSTUNNAT traversalICE
ByteDance ADFE Team
Written by

ByteDance ADFE Team

Official account of ByteDance Advertising Frontend Team

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.