You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Apache服务器上创建无需JavaScript的PHP简易WebSocket聊天应用

PHP WebSocket Implementation (No JavaScript Dependency)

Hey folks, I recently tackled building a WebSocket feature using PHP, and I wanted to share my solution because I had a really tough time finding reliable resources for this.

When I first started researching, I noticed almost all guides and discussions focus exclusively on JavaScript implementations with full source code—there's a huge gap when it comes to solid PHP-based content. I went through several TutorialsPoint articles and YouTube tutorials, but many of them had errors that left me stuck for hours.

After working through those bugs, I finally got a fully functional PHP WebSocket up and running that doesn't require any JavaScript at all. I'm posting this to help other beginners who might be struggling to set up a PHP WebSocket without relying on JS.

Critical Prerequisite

Before you run any of this code, make sure the socket extension is enabled in your php.ini file. This is non-negotiable—PHP can't create sockets without this extension, so double-check this first!

Working Code

Below is the complete code for both the server and client:

PHP WebSocket Server

<?php
$host = 'localhost';
$port = 8080;

// Create socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, $host, $port);
socket_listen($socket);

$clients = [$socket];

while (true) {
    $read = $clients;
    socket_select($read, $write, $except, null);

    foreach ($read as $sock) {
        if ($sock == $socket) {
            $newClient = socket_accept($socket);
            $clients[] = $newClient;
            $header = socket_read($newClient, 1024);
            perform_handshake($header, $newClient, $host, $port);
            socket_getpeername($newClient, $ip);
            echo "New client connected: {$ip}\n";
        } else {
            $data = socket_read($sock, 1024);
            if ($data === false || $data == '') {
                $index = array_search($sock, $clients);
                socket_getpeername($sock, $ip);
                unset($clients[$index]);
                echo "Client disconnected: {$ip}\n";
                continue;
            }
            $decodedData = unmask($data);
            echo "Received message: {$decodedData}\n";
            $response = mask(json_encode(['message' => 'Server received your message: ' . $decodedData]));
            send_message($response, $clients, $sock);
        }
    }
}

function perform_handshake($header, $client, $host, $port) {
    $headers = [];
    $lines = preg_split("/\r\n/", $header);
    foreach ($lines as $line) {
        $line = chop($line);
        if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) {
            $headers[$matches[1]] = $matches[2];
        }
    }

    $secKey = $headers['Sec-WebSocket-Key'];
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
               "Upgrade: websocket\r\n" .
               "Connection: Upgrade\r\n" .
               "WebSocket-Origin: http://{$host}:{$port}\r\n" .
               "WebSocket-Location: ws://{$host}:{$port}/websocket\r\n" .
               "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client, $upgrade, strlen($upgrade));
}

function unmask($text) {
    $length = ord($text[1]) & 127;
    if ($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    } elseif ($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    } else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

function mask($text) {
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if ($length <= 125) {
        $header = pack('CC', $b1, $length);
    } elseif ($length > 125 && $length < 65536) {
        $header = pack('CCn', $b1, 126, $length);
    } elseif ($length >= 65536) {
        $header = pack('CCNN', $b1, 127, $length);
    }
    return $header . $text;
}

function send_message($message, $clients, $sender) {
    foreach ($clients as $client) {
        if ($client != $sender && $client != $clients[0]) {
            socket_write($client, $message, strlen($message));
        }
    }
}
?>

PHP WebSocket Client (No JavaScript)

<?php
$host = 'localhost';
$port = 8080;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, $host, $port);

// Handshake request
$key = base64_encode(openssl_random_pseudo_bytes(16));
$handshake = "GET / HTTP/1.1\r\n" .
             "Host: {$host}:{$port}\r\n" .
             "Upgrade: websocket\r\n" .
             "Connection: Upgrade\r\n" .
             "Sec-WebSocket-Key: {$key}\r\n" .
             "Sec-WebSocket-Version: 13\r\n\r\n";
socket_write($socket, $handshake, strlen($handshake));
$response = socket_read($socket, 1024);

// Send message
$message = "Hello from PHP client!";
$encodedMessage = mask($message);
socket_write($socket, $encodedMessage, strlen($encodedMessage));

// Receive response
$response = socket_read($socket, 1024);
$decodedResponse = unmask($response);
echo "Server response: {$decodedResponse}\n";

socket_close($socket);

function mask($text) {
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if ($length <= 125) {
        $header = pack('CC', $b1, $length);
    } elseif ($length > 125 && $length < 65536) {
        $header = pack('CCn', $b1, 126, $length);
    } elseif ($length >= 65536) {
        $header = pack('CCNN', $b1, 127, $length);
    }
    return $header . $text;
}

function unmask($text) {
    $length = ord($text[1]) & 127;
    if ($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    } elseif ($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    } else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}
?>

内容的提问来源于stack exchange,提问作者CreativeMinds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:21:41