如何在Apache服务器上创建无需JavaScript的PHP简易WebSocket聊天应用
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

