Back to Technology

Complete Protocols Master Part 11: Real-Time Protocols

January 31, 2026 Wasil Zafar 40 min read

Master real-time communication: WebSockets for bidirectional messaging, WebRTC for peer-to-peer video, SIP/RTP for VoIP, and XMPP for chat applications.

Table of Contents

  1. Introduction
  2. WebSockets
  3. Server-Sent Events
  4. WebRTC
  5. SIP & RTP (VoIP)
  6. XMPP (Chat)
  7. Comparison
  8. Summary

Introduction: Real-Time Communication

HTTP's request-response model doesn't work for real-time applications. When you need instant updates—chat messages, live scores, video calls—you need protocols designed for bidirectional, low-latency communication.

Series Context: This is Part 11 of 20 in the Complete Protocols Master series. Real-time protocols operate at the Application Layer, often building on TCP (WebSockets), UDP (RTP), or both (WebRTC).
Overview

Real-Time Protocol Landscape

ProtocolUse CaseTransportBrowser Support
WebSocketsBidirectional messagingTCP✅ Native
SSEServer push (one-way)HTTP✅ Native
WebRTCP2P audio/videoUDP/TCP✅ Native
SIPCall signalingTCP/UDP❌ SIP.js
RTPMedia streamingUDPVia WebRTC
XMPPIM/PresenceTCPStanza.io
# Real-time vs Request-Response

# HTTP: Request-Response
# Client: "Any new messages?"
# Server: "No"
# (1 second later)
# Client: "Any new messages?"
# Server: "No"
# (Polling wastes bandwidth, adds latency)

# WebSocket: Bidirectional
# Client: "Open connection"
# Server: "Connected"
# Server: "New message: Hello!"  (instant push)
# Client: "Send: Hi back!"
# (Connection stays open)

# Key differences:
comparison = {
    "HTTP Polling": {
        "connection": "Open, close, repeat",
        "latency": "High (request interval)",
        "bandwidth": "High (headers each time)",
        "bidirectional": False
    },
    "WebSocket": {
        "connection": "Persistent",
        "latency": "Low (instant)",
        "bandwidth": "Low (minimal framing)",
        "bidirectional": True
    }
}

for proto, features in comparison.items():
    print(f"\n{proto}:")
    for key, value in features.items():
        print(f"  {key}: {value}")

WebSockets

WebSockets (RFC 6455) provide full-duplex communication over a single TCP connection. They're the foundation of real-time web applications—chat, gaming, live updates.

Handshake

WebSocket Connection Upgrade

WebSocket starts as HTTP, then upgrades:

CLIENT REQUEST:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

SERVER RESPONSE:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

After this handshake:
• No more HTTP headers
• Binary framing only
• Full-duplex communication
• Either side can send anytime
# WebSocket server with Python (websockets library)

async def websocket_server_example():
    """WebSocket server demonstration"""
    
    print("WebSocket Server Example")
    print("=" * 50)
    
    print("""
    import asyncio
    import websockets
    
    # Store connected clients
    clients = set()
    
    async def handler(websocket, path):
        # Register client
        clients.add(websocket)
        try:
            async for message in websocket:
                print(f"Received: {message}")
                
                # Broadcast to all clients
                for client in clients:
                    if client != websocket:
                        await client.send(f"User said: {message}")
        finally:
            clients.remove(websocket)
    
    # Start server
    async def main():
        async with websockets.serve(handler, "localhost", 8765):
            print("WebSocket server running on ws://localhost:8765")
            await asyncio.Future()  # Run forever
    
    asyncio.run(main())
    """)
    
    print("\nInstall: pip install websockets")

asyncio.run(websocket_server_example()) if 'asyncio' in dir() else websocket_server_example()
// WebSocket client (JavaScript)

// Browser WebSocket API
const socket = new WebSocket('wss://server.example.com/chat');

// Connection opened
socket.addEventListener('open', (event) => {
    console.log('Connected!');
    socket.send('Hello Server!');
});

// Listen for messages
socket.addEventListener('message', (event) => {
    console.log('Message from server:', event.data);
});

// Connection closed
socket.addEventListener('close', (event) => {
    console.log('Disconnected');
});

// Handle errors
socket.addEventListener('error', (error) => {
    console.error('WebSocket error:', error);
});

// Send message
function sendMessage(text) {
    if (socket.readyState === WebSocket.OPEN) {
        socket.send(text);
    }
}

// Close connection
function disconnect() {
    socket.close();
}
Socket.io

Socket.io: WebSocket with Fallbacks

// Socket.io adds: reconnection, rooms, namespaces

// Server (Node.js)
const io = require('socket.io')(3000);

io.on('connection', (socket) => {
    console.log('Client connected:', socket.id);
    
    // Join a room
    socket.join('room-123');
    
    // Listen for events
    socket.on('chat message', (msg) => {
        // Broadcast to room
        io.to('room-123').emit('chat message', msg);
    });
    
    socket.on('disconnect', () => {
        console.log('Client disconnected');
    });
});

// Client (Browser)
const socket = io('http://localhost:3000');

socket.on('connect', () => {
    console.log('Connected!');
});

socket.emit('chat message', 'Hello everyone!');

socket.on('chat message', (msg) => {
    console.log('Message:', msg);
});

Server-Sent Events (SSE)

SSE provides one-way server-to-client streaming over HTTP. Simpler than WebSockets when you only need server push (notifications, live feeds).

SSE vs WebSocket

When to Use SSE

SSE Advantages:
• Simpler than WebSocket
• Works over HTTP/2 (multiplexing)
• Auto-reconnection built-in
• Event IDs for resume after disconnect

SSE Limitations:
• One-way only (server → client)
• Text data only (no binary)
• Limited connections per browser (6 HTTP/1.1)

Use SSE for:
✅ Live scores
✅ News feeds
✅ Notifications
✅ Stock tickers

Use WebSocket for:
✅ Chat (bidirectional)
✅ Gaming (low latency)
✅ Collaborative editing
# SSE server with Python (Flask)

from flask import Flask, Response
import time

app = Flask(__name__)

def generate_events():
    """Generator for SSE events"""
    count = 0
    while True:
        count += 1
        # SSE format: data: message\n\n
        yield f"data: Event {count} at {time.strftime('%H:%M:%S')}\n\n"
        time.sleep(1)

@app.route('/events')
def events():
    return Response(
        generate_events(),
        mimetype='text/event-stream',
        headers={
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
        }
    )

# Run: flask run
# Client connects to /events and receives stream
// SSE client (JavaScript)

// Create EventSource
const eventSource = new EventSource('/events');

// Listen for messages
eventSource.onmessage = (event) => {
    console.log('Received:', event.data);
};

// Named events
eventSource.addEventListener('notification', (event) => {
    console.log('Notification:', event.data);
});

// Error handling (auto-reconnects)
eventSource.onerror = (error) => {
    console.error('SSE error:', error);
};

// Close connection
// eventSource.close();

WebRTC: Browser Peer-to-Peer

WebRTC (Web Real-Time Communication) enables peer-to-peer audio, video, and data directly between browsers—no plugins needed. Powers video calls, screen sharing, and file transfer.

P2P But Needs Servers: WebRTC is peer-to-peer for media, but still needs: (1) Signaling server to exchange connection info, (2) STUN/TURN servers to traverse NAT/firewalls.
Architecture

WebRTC Connection Flow

WebRTC Connection Steps:

1. SIGNALING (via WebSocket/HTTP)
   • Exchange SDP (Session Description Protocol)
   • Describes media capabilities

2. ICE CANDIDATE GATHERING
   • STUN: Discover public IP/port
   • TURN: Relay if direct P2P fails
   
3. ICE CONNECTIVITY CHECKS
   • Try all candidate pairs
   • Select best path (usually direct P2P)

4. DTLS HANDSHAKE
   • Secure the connection
   • Exchange encryption keys

5. MEDIA/DATA FLOW
   • SRTP for audio/video (encrypted RTP)
   • SCTP for data channels

STUN vs TURN:
STUN: "What's my public IP?" (cheap, just discovery)
TURN: "Relay my traffic" (expensive, when P2P fails)
// WebRTC peer connection example

// Create peer connection
const config = {
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        { 
            urls: 'turn:turn.example.com',
            username: 'user',
            credential: 'pass'
        }
    ]
};

const pc = new RTCPeerConnection(config);

// Handle ICE candidates
pc.onicecandidate = (event) => {
    if (event.candidate) {
        // Send candidate to peer via signaling server
        sendToSignaling({ type: 'candidate', candidate: event.candidate });
    }
};

// Handle incoming tracks (audio/video)
pc.ontrack = (event) => {
    document.getElementById('remoteVideo').srcObject = event.streams[0];
};

// Add local media
async function startCall() {
    const stream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true
    });
    
    // Show local video
    document.getElementById('localVideo').srcObject = stream;
    
    // Add tracks to peer connection
    stream.getTracks().forEach(track => pc.addTrack(track, stream));
    
    // Create and send offer
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    sendToSignaling({ type: 'offer', sdp: offer });
}

// Handle incoming offer
async function handleOffer(offer) {
    await pc.setRemoteDescription(new RTCSessionDescription(offer));
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    sendToSignaling({ type: 'answer', sdp: answer });
}

// Handle incoming answer
async function handleAnswer(answer) {
    await pc.setRemoteDescription(new RTCSessionDescription(answer));
}

// Handle incoming ICE candidate
async function handleCandidate(candidate) {
    await pc.addIceCandidate(new RTCIceCandidate(candidate));
}
Data Channels

WebRTC for Data (Not Just Video)

// WebRTC Data Channels: P2P data transfer

const pc = new RTCPeerConnection(config);

// Create data channel (initiator)
const dataChannel = pc.createDataChannel('chat', {
    ordered: true,      // Guarantee order
    maxRetransmits: 3   // Reliability
});

dataChannel.onopen = () => {
    console.log('Data channel open');
    dataChannel.send('Hello peer!');
};

dataChannel.onmessage = (event) => {
    console.log('Received:', event.data);
};

// Handle incoming data channel (responder)
pc.ondatachannel = (event) => {
    const channel = event.channel;
    channel.onmessage = (e) => console.log('Received:', e.data);
};

// Use cases:
// • P2P file transfer (no server storage!)
// • Low-latency gaming
// • Collaborative editing

SIP & RTP: VoIP Protocols

SIP (Session Initiation Protocol) handles call signaling—ringing, answering, hanging up. RTP (Real-time Transport Protocol) carries the actual audio/video.

SIP Basics

SIP Call Flow

SIP Call Setup:

Alice                 Server                 Bob
  |                     |                     |
  |------ INVITE ------>|                     |
  |                     |------ INVITE ------>|
  |                     |<----- 180 Ringing --|
  |<---- 180 Ringing ---|                     |
  |                     |<----- 200 OK -------|
  |<---- 200 OK --------|                     |
  |------- ACK -------->|                     |
  |                     |------- ACK -------->|
  |                     |                     |
  |<========== RTP Media Flow =============>|
  |                     |                     |
  |------- BYE -------->|                     |
  |                     |------- BYE -------->|
  |                     |<----- 200 OK -------|
  |<---- 200 OK --------|                     |

SIP Methods:
INVITE    - Start call
ACK       - Confirm INVITE
BYE       - End call
CANCEL    - Cancel pending INVITE
REGISTER  - Register with server
OPTIONS   - Query capabilities
# SIP INVITE message example

INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP alice-pc.example.com:5060
From: "Alice" <sip:alice@example.com>;tag=1234
To: "Bob" <sip:bob@example.com>
Call-ID: 987654321@alice-pc.example.com
CSeq: 1 INVITE
Contact: <sip:alice@alice-pc.example.com:5060>
Content-Type: application/sdp
Content-Length: 200

v=0
o=alice 2890844526 2890844526 IN IP4 alice-pc.example.com
s=Phone Call
c=IN IP4 alice-pc.example.com
t=0 0
m=audio 49170 RTP/AVP 0 8 97
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 opus/48000/2
RTP

RTP: Real-time Transport Protocol

RTP Header (12 bytes minimum):

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       Sequence Number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             SSRC                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Payload                            |

Key Fields:
V  = Version (2)
PT = Payload Type (codec: 0=PCMU, 8=PCMA, etc.)
Sequence = Order packets (detect loss)
Timestamp = Synchronize playback
SSRC = Source identifier

RTP uses UDP because:
• Low latency (no retransmission delay)
• Packet loss acceptable (brief glitch vs delay)
• Timing critical (can't wait for retransmit)

XMPP: Extensible Messaging

XMPP (Extensible Messaging and Presence Protocol) is an open standard for instant messaging, presence, and multi-user chat. Used by WhatsApp (modified), Google Talk, and many enterprise chat systems.

XMPP Stanzas

XMPP Message Format (XML)

<!-- Message Stanza -->
<message from="alice@example.com" 
         to="bob@example.com" 
         type="chat">
    <body>Hello Bob!</body>
</message>

<!-- Presence Stanza -->
<presence from="alice@example.com">
    <show>away</show>
    <status>In a meeting</status>
</presence>

<!-- IQ (Info/Query) Stanza -->
<iq type="get" id="roster1">
    <query xmlns="jabber:iq:roster"/>
</iq>

XMPP Stanza Types:
• message - Chat messages
• presence - Online status
• iq - Request/response queries
# XMPP client example (slixmpp library)

def demonstrate_xmpp():
    """Show XMPP concepts"""
    
    print("XMPP Example (slixmpp)")
    print("=" * 50)
    
    print("""
    import slixmpp
    
    class ChatBot(slixmpp.ClientXMPP):
        def __init__(self, jid, password):
            super().__init__(jid, password)
            
            # Event handlers
            self.add_event_handler('session_start', self.start)
            self.add_event_handler('message', self.message)
        
        async def start(self, event):
            # Send presence
            self.send_presence()
            # Get contact list
            await self.get_roster()
        
        def message(self, msg):
            if msg['type'] == 'chat':
                print(f"From {msg['from']}: {msg['body']}")
                # Reply
                msg.reply(f"You said: {msg['body']}").send()
    
    # Connect
    bot = ChatBot('bot@example.com', 'password')
    bot.connect()
    bot.process(forever=True)
    """)
    
    print("\nXMPP Features:")
    print("• Federated (anyone can run a server)")
    print("• Multi-user chat (MUC) rooms")
    print("• End-to-end encryption (OMEMO)")
    print("• Extensible via XEPs")

demonstrate_xmpp()

Protocol Comparison

Decision Guide

Choosing the Right Protocol

Use CaseBest ChoiceReason
Chat applicationWebSocket / Socket.ioBidirectional, low latency
Live notificationsSSESimpler, HTTP/2 friendly
Video conferencingWebRTCP2P, low latency
VoIP / PBXSIP + RTPStandard, interoperable
IM with presenceXMPPFederated, feature-rich
Gaming (browser)WebSocket + WebRTCLow latency, P2P data
Stock tickerSSEOne-way, auto-reconnect
# Protocol selection helper

def recommend_protocol(use_case):
    """Recommend real-time protocol based on use case"""
    
    recommendations = {
        "bidirectional_chat": {
            "protocol": "WebSocket",
            "library": "Socket.io / ws",
            "reason": "Full-duplex, reliable delivery"
        },
        "server_notifications": {
            "protocol": "Server-Sent Events",
            "library": "Native EventSource",
            "reason": "Simple, auto-reconnect, HTTP/2"
        },
        "video_call": {
            "protocol": "WebRTC",
            "library": "Simple-peer / Mediasoup",
            "reason": "P2P, low latency, native browser"
        },
        "voip_pbx": {
            "protocol": "SIP + RTP",
            "library": "Opal / FreeSWITCH",
            "reason": "Telephony standard, PSTN interop"
        },
        "file_transfer_p2p": {
            "protocol": "WebRTC Data Channel",
            "library": "Simple-peer",
            "reason": "Direct P2P, no server storage"
        },
        "live_collaboration": {
            "protocol": "WebSocket + OT/CRDT",
            "library": "Y.js / ShareDB",
            "reason": "Real-time sync, conflict resolution"
        }
    }
    
    if use_case in recommendations:
        rec = recommendations[use_case]
        return f"{rec['protocol']} ({rec['library']}) - {rec['reason']}"
    return "WebSocket (general purpose)"

print("Protocol Recommendations")
print("=" * 50)
for case in ["bidirectional_chat", "server_notifications", "video_call", "voip_pbx"]:
    print(f"\n{case}:")
    print(f"  → {recommend_protocol(case)}")

Summary & Next Steps

Key Takeaways:
  • WebSocket: Bidirectional over TCP, foundation for real-time web
  • SSE: Server push only, simpler than WebSocket
  • WebRTC: P2P audio/video/data, requires signaling
  • SIP/RTP: VoIP standard, telephony interoperability
  • XMPP: Open IM standard, federated architecture
Quiz

Test Your Knowledge

  1. WebSocket vs HTTP difference? (Persistent, bidirectional)
  2. When to use SSE over WebSocket? (Server-push only, simpler)
  3. Why does WebRTC need signaling? (Exchange SDP, ICE candidates)
  4. STUN vs TURN? (Discovery vs relay)
  5. What protocol carries VoIP audio? (RTP)

Next in the Series

In Part 12: Streaming Protocols, we'll explore HLS, DASH, and RTMP for video streaming at scale.