在构建 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。例如: