Implementing a WebRTC Signaling Server with PHP Swoole and a Browser Client Demo

This article explains WebRTC fundamentals, key APIs, and demonstrates how to build a browser‑based peer‑to‑peer video chat by implementing a lightweight signaling server in PHP using Swoole coroutines, complete with client‑side JavaScript code, server logic, and deployment tips.

Xueersi Online School Tech Team
Xueersi Online School Tech Team
Xueersi Online School Tech Team
Implementing a WebRTC Signaling Server with PHP Swoole and a Browser Client Demo

WebRTC is an open‑source library for real‑time audio, video, and data communication that works across browsers, Android, and iOS. The article first introduces basic concepts such as Track (individual audio or video stream) and MediaStream (a collection of tracks).

Key WebRTC classes are described: MediaStream for grouping tracks, RTCPeerConnection for handling connection management, NAT traversal, and media exchange, and RTCDataChannel for non‑media data.

The end‑to‑end connection process is outlined, covering media negotiation via SDP, network negotiation using STUN/TURN, and the role of a signaling server to exchange offers, answers, and ICE candidates.

Client‑side implementation (HTML/JavaScript) is provided to capture local media, create a WebSocket connection to the signaling server, and manage the WebRTC peer connection lifecycle. The code is shown below:

<body>
  <div style="display: block">
    <button class="btn" onclick="start()">连接</button>
    <button class="btn" onclick="leave()">离开</button>
  </div>
  <div>
    <div class="videos">
      <h1>Local</h1>
      <video id="localVideo" autoplay></video>
    </div>
    <div class="videos">
      <h1>Remote</h1>
      <video id="remoteVideo" autoplay></video>
    </div>
  </div>
  <script src="assets/js/adapter.js"></script>
  <script type="text/javascript">
    const ws_config = '<?= $signaling_server ?>';
    const localVideo = document.getElementById('localVideo');
    const remoteVideo = document.getElementById('remoteVideo');
    const configuration = { iceServers: [{ urls: '<?= $stun_server ?>' }] };
    // ... (rest of the JavaScript logic for start, leave, ICE handling, publish, subscribe)
  </script>
</body>

The signaling server is implemented in PHP using Swoole's coroutine HTTP server. It handles WebSocket upgrades, maintains a map of subjects (rooms) to connections, and forwards subscribe and publish messages between peers. The core server code is:

<?php
use Swoole\Http\Request;
use Swoole\Http\Response;

Co\run(function () {
    $server = new Swoole\Coroutine\Http\Server('0.0.0.0', 9509, true);
    $server->set([
        'ssl_key_file'  => __DIR__ . '/ssl/ssl.key',
        'ssl_cert_file' => __DIR__ . '/ssl/ssl.crt',
    ]);
    $server->handle('/', function (Request $req, Response $resp) {
        if (isset($req->header['upgrade']) && $req->header['upgrade'] == 'websocket') {
            $resp->upgrade();
            $resp->subjects = [];
            while (true) {
                $frame = $resp->recv();
                if (empty($frame)) break;
                $data = json_decode($frame->data, true);
                switch ($data['cmd']) {
                    case 'subscribe':
                        subscribe($data, $resp);
                        break;
                    case 'publish':
                        publish($data, $resp);
                        break;
                }
            }
            free_connection($resp);
            return;
        }
        // HTTP file serving omitted for brevity
    });
    $server->start();
});

function subscribe($data, $connection) { /* ... */ }
function publish($data, $current_conn) { /* ... */ }
function free_connection($connection) { /* ... */ }
?>

The article also analyses the request flow: the client creates a WebSocket, registers the room, obtains local media, sends a call event, and then exchanges SDP offers/answers and ICE candidates through the signaling server. The server simply broadcasts messages to all other participants in the same room.

Performance considerations are discussed: Swoole coroutines enable millions of concurrent connections with low memory overhead, using EPOLL for event multiplexing. For multi‑core scaling, a process pool with reuse‑port can be employed.

Finally, the author provides a link to the full source repository and notes the runtime environment (PHP 7.2, Swoole 4.4, macOS/Ubuntu). The tutorial concludes with a call for feedback and mentions upcoming Swoole series articles.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Web DevelopmentPHPreal-time communicationWebRTCSwooleSignaling Server
Xueersi Online School Tech Team
Written by

Xueersi Online School Tech Team

The Xueersi Online School Tech Team, dedicated to innovating and promoting internet education technology.

0 followers
Reader feedback

How this landed with the community

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.