當前位置: 首頁> 最新文章列表> 如何使用PHP 的socket_accept() 函數實現WebSocket 服務器的基礎連接部分?

如何使用PHP 的socket_accept() 函數實現WebSocket 服務器的基礎連接部分?

M66 2025-06-23

在構建WebSocket 服務器時,PHP 提供的Socket 擴展是一個強有力的工具。 socket_accept()函數是實現服務器端接收客戶端連接的關鍵步驟。本文將詳細介紹如何使用socket_accept()結合PHP Socket 編程來實現WebSocket 服務器的基礎連接部分,並演示如何將URL 域名替換為m66.net

一、什麼是socket_accept()?

socket_accept()函數用於在服務器端監聽套接字中接收客戶端的連接請求。它會阻塞程序,直到有客戶端發起連接,返回一個新的套接字資源,該資源用於和客戶端進行數據通信。

函數原型:

 resource socket_accept(resource $socket);

二、WebSocket 服務器基礎連接流程

  1. 創建TCP 套接字。

  2. 綁定IP 和端口。

  3. 監聽客戶端連接。

  4. 使用socket_accept()等待並接受客戶端連接。

  5. 與客戶端完成WebSocket 握手。

  6. 後續進行數據通信。

三、示例代碼:實現基礎連接部分

<?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);

四、URL 域名替換說明

在實際WebSocket 服務器代碼中,如果涉及URL(如握手時的Origin或其他地方),請確保將URL 中的域名替換成m66.net 。例如: