您的位置:

PHP Socket长连接的应用

一、什么是PHP Socket长连接

Socket是一个抽象层,它允许程序在网络环境中发送和接收数据。使用Socket时,程序将创建一个Socket对象,并用它来代表一个网络连接,可以发送数据和接收数据。

在PHP中,通过socket扩展可以很方便地使用Socket API,实现TCP/UDP协议的通信。其中,PHP Socket长连接指建立Socket连接后,长时间保持连接状态,能够发送多个请求和接收多个数据包,以及服务器在一段时间没有数据包传输时自动关闭连接。

二、PHP Socket长连接的优点

1、降低网络连接时延:长连接可以避免频繁地建立和断开网络连接,减少网络连接的时延。

2、减轻服务器资源压力:在每个连接间产生的握手协议、安全协议、重复发送的HTTP头必须消耗额外的带宽和享元模式,通过长连接可以减少网络开销,减轻服务器压力。

3、隐藏网络延迟:使用长连接可以减少网络开销,缓存请求在服务端的答复,避免一次没有完全填充的请求等待下一次完整的请求。从而有效地将网络延迟隐藏在网络背景中,提高用户体验。

三、PHP Socket长连接的应用

1、聊天室

我们可以使用PHP Socket长连接来实现聊天室功能。当用户在网页上输入聊天内容后,客户端将该内容以Socket长连接方式发送到后台,并放入消息队列中,服务端读取消息队列并再次发送给所有的聊天室用户。


//PHP长连接服务端代码示例
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sock, "0.0.0.0", 9999);
socket_listen($sock);
$clients = array($sock);
while (true) {
    $read = $clients;
    $write = null;
    $err = null;
    if (socket_select($read, $write, $err, 5) < 1) {
        continue;
    }
    if (in_array($sock, $read)) {
        $clients[] = $newsock = socket_accept($sock);
        $header = PHP_EOL.'Welcome to chat-demo'.PHP_EOL.'Enter your name: ';

        @socket_write($newsock, $header, strlen($header));
        unset($read[ array_search( $sock, $read ) ]);
    }
 
    foreach ($read as $read_sock) {
        $data = @socket_read($read_sock, 2048, PHP_NORMAL_READ);
        if ($data === false) {
            socket_close($read_sock);
            $key_to_remove = array_search($read_sock, $clients, true);
            unset($clients[$key_to_remove]);
            break;
        }
        $data = trim($data);
        if (!empty($data)) {
            foreach ($clients as $send_sock) {
                if ($send_sock == $sock || $send_sock == $read_sock){
                    continue;
                }
                @socket_write($send_sock, $data, strlen($data));
            }
        }
    }
}

2、即时通讯

使用PHP Socket长连接可以实现即时通讯功能。比如,客户端可以将用户输入的文本消息以及相关的用户信息,通过Socket长连接方式提交到服务器端,服务器端收到后可以通过Websocket将消息推送给所有需要的在线用户。


//PHP长连接服务端代码示例
set_time_limit(0);
error_reporting(E_ALL & ~E_NOTICE);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 9999);
socket_listen($socket);

$clients = array();
while (true) {
    $read = $clients; 
    $read[] = $socket;

    socket_select($read, $write, $except, null);

    foreach ($read as $connect_socket) {
        if ($connect_socket == $socket) { 
            $new_socket = socket_accept($connect_socket);
            if ($new_socket) {
                $clients[] = $new_socket;
            }
        } else {
            $bytes = @socket_recv($connect_socket, $buffer, 1024, MSG_DONTWAIT);
            if ($bytes) {
                if (preg_match('/(.*): (.*)/', $buffer, $matches) == 1) {
                    $name = $matches[1];
                    $message = $matches[2];
                    $response = $name . ':' . $message . "\n";
                } else {
                    $response = "robot: " . $buffer;
                }

                foreach ($clients as $client) {
                    @socket_write($client, $response, strlen($response));
                }
            }
            if ($bytes === false) {
                $key_to_remove = array_search($connect_socket, $clients, true);
                unset($clients[$key_to_remove]);
                socket_shutdown($connect_socket, 2);
                socket_close($connect_socket);
            }
        }
    }
}

3、定时器

PHP中没有自带的“计时器”功能,但使用Socket长连接可以轻松实现定时器功能。当需要创建一个任务,在指定的时间间隔内运行该任务时,可以在客户端启动Socket服务端程序,并在连接建立后开启一个周期性的定时器。这样,在一定时间后,服务端程序会主动调用客户端指定的函数。


//PHP长连接客户端代码示例
set_time_limit(0);
$host = 'localhost';
$port = 2345;
$conn = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (socket_connect($conn, $host, $port) === false) {
    die("ERROR: " . socket_strerror(socket_last_error()) . "\n");
}

$next_call_time = time();

while (true) {
    $time_left = $next_call_time - time();
    if ($time_left > 0) {
        usleep(1000000 * $time_left);
    }
    $next_call_time += 5;
    socket_write($conn, 'time to do something ...');
}

四、总结

PHP Socket长连接可以有效地缓解网络延迟、减少服务器资源压力,具有很多实际应用场景。上述示例演示了使用PHP Socket长连接实现聊天室、即时通讯、定时器等功能的方法。如需使用PHP Socket长连接应用到您的项目中,可以参考以上示例代码,根据实际情况进行调整和扩展。