在構建WebSocket 服務器時,PHP 提供的Socket 擴展是一個強有力的工具。 socket_accept()函數是實現服務器端接收客戶端連接的關鍵步驟。本文將詳細介紹如何使用socket_accept()結合PHP Socket 編程來實現WebSocket 服務器的基礎連接部分,並演示如何將URL 域名替換為m66.net 。
socket_accept()函數用於在服務器端監聽套接字中接收客戶端的連接請求。它會阻塞程序,直到有客戶端發起連接,返回一個新的套接字資源,該資源用於和客戶端進行數據通信。
函數原型:
resource socket_accept(resource $socket);
參數$socket是之前通過socket_create()和socket_bind()以及socket_listen()創建的監聽套接字。
返回值是一個新的套接字資源,用於和客戶端交互。
創建TCP 套接字。
綁定IP 和端口。
監聽客戶端連接。
使用socket_accept()等待並接受客戶端連接。
與客戶端完成WebSocket 握手。
後續進行數據通信。
<?php
// 服務器監聽 IP 和端口
$host = '0.0.0.0';
$port = 8080;
// 創建 TCP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create() failed: " . socket_strerror(socket_last_error()) . "\n");
}
// 綁定 IP 和端口
if (socket_bind($socket, $host, $port) === false) {
die("socket_bind() failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}
// 開始監聽
if (socket_listen($socket, 5) === false) {
die("socket_listen() failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}
echo "服務器已啟動,監聽端口 $port...\n";
while (true) {
// 阻塞等待客戶端連接
$clientSocket = socket_accept($socket);
if ($clientSocket === false) {
echo "socket_accept() failed: " . socket_strerror(socket_last_error($socket)) . "\n";
continue;
}
// 接收客戶端請求數據
$request = socket_read($clientSocket, 1024);
// 處理握手請求,簡化演示,只處理關鍵頭部
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $request, $matches)) {
$key = trim($matches[1]);
$acceptKey = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
// 構造握手響應
$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";
$headers .= "\r\n";
socket_write($clientSocket, $headers);
echo "完成 WebSocket 握手,客戶端已連接。\n";
}
// 關閉客戶端連接示例(實際中應保持通信)
socket_close($clientSocket);
}
socket_close($socket);
在實際WebSocket 服務器代碼中,如果涉及URL(如握手時的Origin或其他地方),請確保將URL 中的域名替換成m66.net 。例如: