函数名:socket_select()
适用版本:PHP 4 >= 4.3.0, PHP 5, PHP 7
函数描述:socket_select()函数用于在给定的一组socket上进行阻塞式I/O操作的多路复用。它可以同时监视多个socket,以确定哪些socket上有输入、输出或异常事件发生。这个函数是基于操作系统提供的select系统调用实现的。
语法:int socket_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] )
参数:
- $read: 一个包含需要监视读事件的socket的数组。
- $write: 一个包含需要监视写事件的socket的数组。
- $except: 一个包含需要监视异常事件的socket的数组。
- $tv_sec: 超时时间,以秒为单位。如果为0,则表示无限等待。
- $tv_usec: 超时时间的微秒部分。默认值为0。
返回值:
- 如果至少有一个socket准备好读、写或有异常,则返回值大于0。
- 如果超时时间到达,则返回值为0。
- 如果发生错误,则返回值为-1。
示例:
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, '127.0.0.1', 8888);
socket_listen($serverSocket);
$clientSockets = array($serverSocket);
$write = $except = array();
while (true) {
$read = $clientSockets; // 用于监视读事件的socket数组
// 使用socket_select()等待事件发生
if (socket_select($read, $write, $except, 0) < 1) {
continue;
}
// 检查是否有新的客户端连接
if (in_array($serverSocket, $read)) {
$clientSocket = socket_accept($serverSocket);
$clientSockets[] = $clientSocket;
echo "New client connected." . PHP_EOL;
// 从读事件数组中移除服务器socket
$key = array_search($serverSocket, $read);
unset($read[$key]);
}
// 处理已连接的客户端发送的数据
foreach ($read as $clientSocket) {
$data = socket_read($clientSocket, 1024);
if ($data === false) {
// 客户端断开连接
$key = array_search($clientSocket, $clientSockets);
unset($clientSockets[$key]);
socket_close($clientSocket);
echo "Client disconnected." . PHP_EOL;
} else {
// 处理客户端发送的数据
echo "Received data: " . $data . PHP_EOL;
}
}
}
// 关闭服务器socket
socket_close($serverSocket);
上述示例演示了一个简单的TCP服务器,使用socket_select()函数来实现多路复用。在循环中,通过socket_select()等待事件发生,然后根据返回结果处理不同的情况,如有新的客户端连接、客户端断开连接和接收客户端发送的数据。这种方式可以在单个线程中同时处理多个客户端连接,提高服务器的性能和并发处理能力。