以下是一个简单的PHP WebSocket服务器的实现。它可以监听来自客户端的连接,并处理消息发送和接收:
class WebSocket
{
private $sockets = [];
private $clients = [];
public function __construct($host, $port)
{
$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);
$this->sockets[] = $socket;
echo "Server started\nListening on: $host:$port\n";
while (true) {
$this->handleSockets();
}
}
private function handleSockets()
{
$readSockets = $this->sockets;
$writeSockets = [];
$exceptSockets = null;
socket_select($readSockets, $writeSockets, $exceptSockets, null);
foreach ($readSockets as $socket) {
if ($socket == $this->sockets[0]) {
// new connection
$clientSocket = socket_accept($socket);
$this->sockets[] = $clientSocket;
$this->clients[] = ['socket' => $clientSocket, 'handshake' => false];
echo "New client connected\n";
} else {
$client = $this->getClientBySocket($socket);
if (!$client['handshake']) {
// handshake
$this->doHandshake($client, socket_read($socket, 1024));
} else {
// handle message
$message = socket_read($socket, 1024);
if ($message === "") {
// client disconnected
$this->disconnectClient($client);
} else {
$this->sendToAllClients($message);
}
}
}
}
}
private function doHandshake(&$client, $data)
{
$headers = [];
$lines = preg_split("/\r\n/", $data);
foreach ($lines as $line) {
if (strpos($line, ':') !== false) {
list($key, $value) = explode(':', $line, 2);
$headers[strtolower(trim($key))] = trim($value);
}
}
$secKey = $headers['sec-websocket-key'];
$secAccept = base64_encode(sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$response = "HTTP/1.1 101 Switching Protocols\r\n";
$response .= "Upgrade: websocket\r\n";
$response .= "Connection: Upgrade\r\n";
$response .= "Sec-WebSocket-Accept: $secAccept\r\n\r\n";
socket_write($client['socket'], $response, strlen($response));
$client['handshake'] = true;
}
private function disconnectClient(&$client)
{
$index = array_search($client, $this->clients);
socket_close($client['socket']);
unset($this->clients[$index]);
$this->clients = array_values($this->clients);
echo "Client disconnected\n";
}
private function getClientBySocket($socket)
{
foreach ($this->clients as &$client) {
if ($socket == $client['socket']) {
return $client;
}
}
}
private function sendToAllClients($message)
{
foreach ($this->clients as &$client) {
socket_write($client['socket'], $message, strlen($message));
}
}
}
new WebSocket('localhost', 8888);
使用:
启动服务器:
php websocket.php
在浏览器中打开WebSocket客户端,连接服务器并发送消息:
var socket = new WebSocket('ws://localhost:8888');
socket.onopen = function(e) {
console.log('WebSocket connected');
socket.send('Hello WebSocket');
};
socket.onmessage = function(e) {
console.log('Received message:', e.data);
};