一、什麼是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長連接應用到您的項目中,可以參考以上示例代碼,根據實際情況進行調整和擴展。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/250504.html