Webアプリケーションでは、WebSocketは、クライアントとサーバーの間に完全な二重通信チャネルを確立する方法を提供します。従来のHTTP要求と比較して、WebSocketにより、サーバーはクライアントに積極的にメッセージをプッシュできます。 PHPは、従来の意味での長い接続に最も適した言語ではありませんが、基礎となるソケットプログラミングを通じて単純なWebSocketサービスを実装できます。この記事では、PHPのsocket_accept関数を使用して、フロントエンドWebsocketクライアントとの通信を実現する方法を紹介します。
PHPのソケット機能を使用するには、PHPでソケット拡張機能が有効になっていることを確認する必要があります。 php.iniで有効にすることができます:
extension=sockets
次に、PHPサービスを再起動します。
WebSocketの握手プロセスは、特定のプロトコル仕様に従います。 WebSocket Data Frame通信を実行する前に、クライアントリクエストを受信した後、HTTPプロトコルレベルの握手確認を実行する必要があります。
これが完全なPHPスクリプトの例です。
<?php
$host = '0.0.0.0';
$port = 8080;
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, $host, $port);
socket_listen($serverSocket);
echo "WebSocket サーバーはから始まります $host:$port\n";
while (true) {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
continue;
}
// クライアントリクエストヘッダーをお読みください
$request = socket_read($clientSocket, 1024);
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $request, $matches)) {
$key = trim($matches[1]);
$acceptKey = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$headers = "HTTP/1.1 101 Switching Protocols\r\n";
$headers .= "Upgrade: websocket\r\n";
$headers .= "Connection: Upgrade\r\n";
$headers .= "Sec-WebSocket-Accept: $acceptKey\r\n\r\n";
socket_write($clientSocket, $headers);
echo "WebSocket 握手が完了しました。\n";
}
// 簡単な読み取りと送信 WebSocket 情報
while (true) {
$data = socket_read($clientSocket, 2048);
if ($data === false) {
break;
}
$decoded = unmask($data);
echo "接收到客户端情報: $decoded\n";
$response = mask("あなたが送ったのは: $decoded");
socket_write($clientSocket, $response);
}
socket_close($clientSocket);
}
socket_close($serverSocket);
// 分析 WebSocket フレーム
function unmask($payload) {
$length = ord($payload[1]) & 127;
if ($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
} elseif ($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
} else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
}
$text = '';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
// 構造 WebSocket 数据フレーム
function mask($text) {
$b1 = 0x81; // FIN=1, opcode=0x1 (text)
$length = strlen($text);
if ($length <= 125) {
$header = pack('CC', $b1, $length);
} elseif ($length <= 65535) {
$header = pack('CCn', $b1, 126, $length);
} else {
$header = pack('CCNN', $b1, 127, 0, $length);
}
return $header . $text;
}
?>
フロントエンドでは、次の方法でPHP Websocketサービスと通信できます。
<script>
const socket = new WebSocket("ws://m66.net:8080");
socket.onopen = () => {
console.log("接続が確立されています");
socket.send("こんにちは PHP WebSocket!");
};
socket.onmessage = (event) => {
console.log("收到情報:", event.data);
};
socket.onclose = () => {
console.log("接続が閉じられています");
};
</script>
注: ws://m66.net:8080これはサーバーのアドレスです。展開環境に従ってドメイン名とポートマッピングを設定してください。
PHPのsocket_acceptおよび関連関数を使用することにより、基本的なWebSocketサーバーロジックを実装できます。この方法は、学習および実験目的に適しています。生産環境の場合、Ratchet、Swooleなどの高性能ソリューションを使用するか、専用のWebsocketサーバー(node.js、goなど)を使用することをお勧めします。
PHPは長い接続用に設計されていませんが、その基礎となるソケットは強力であり、基本的な双方向通信ニーズを満たすことができます。この記事の例を使用して、シンプルなPHP Websocketサーバーを構築して、フロントエンドクライアントと対話できます。