当前位置: 首页> 最新文章列表> 如何使用 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。例如: