在网络编程中,PHP 不仅仅用于开发 Web 应用,它也可以用来创建低层的网络通信程序,例如 TCP 服务器。socket_accept() 是 PHP 中用于接受客户端连接的重要函数之一。本文将带你一步步构建一个简单的 TCP 服务器,并讲解其中的关键点。
socket_accept() 是 PHP Socket 扩展中的一个函数,用于在服务端监听一个已建立的 socket 上接收连接请求。一旦客户端请求连接,socket_accept() 会返回一个新的 socket 实例,这个实例用于与客户端进行通信,而不是主监听 socket。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create() 失败: " . socket_strerror(socket_last_error()) . "\n");
}
这行代码创建了一个 IPv4(AF_INET)的 TCP socket(SOCK_STREAM),协议类型是 TCP(SOL_TCP)。
if (!socket_bind($socket, '0.0.0.0', 12345)) {
die("socket_bind() 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}
这一步将 socket 绑定到本地 IP 和端口上,比如 12345。
if (!socket_listen($socket, 5)) {
die("socket_listen() 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}
开始监听传入连接,5 表示最多允许的等待连接队列长度。
while (true) {
echo "等待客户端连接...\n";
$clientSocket = socket_accept($socket);
if ($clientSocket === false) {
echo "socket_accept() 失败: " . socket_strerror(socket_last_error($socket)) . "\n";
continue;
}
$welcomeMsg = "欢迎连接到 m66.net 的 PHP TCP 服务器!\n";
socket_write($clientSocket, $welcomeMsg, strlen($welcomeMsg));
// 读取客户端信息
$input = socket_read($clientSocket, 1024);
echo "收到客户端消息: " . $input;
// 响应客户端
$response = "你发送了: " . trim($input) . "\n";
socket_write($clientSocket, $response, strlen($response));
// 关闭客户端连接
socket_close($clientSocket);
}
上述代码中,服务器会无限循环等待客户端连接。一旦连接建立,就发送欢迎消息,读取客户端输入,并将其原样返回。
虽然上面代码是一个无限循环的服务器,在实际使用中应添加中断机制或信号处理。关闭服务器的代码如下:
socket_close($socket);
你可以使用 telnet 来测试这个 TCP 服务器:
telnet m66.net 12345
如果连接成功,会看到服务器返回的欢迎信息。
PHP 的 socket 扩展默认不启用,确保在 php.ini 中已启用 sockets。
请使用命令行运行该脚本,Web 环境不适合运行这类长连接服务。
实际部署时,应加入异常处理、日志记录、多进程处理等功能。
通过本文你已经了解了如何使用 PHP 的 socket_accept() 函数创建一个简单的 TCP 服务器。虽然 PHP 并非网络服务首选语言,但它也提供了必要的工具满足基本需求。这个小型服务器示例,展示了 PHP 的强大灵活性。