PHP 不僅能處理 HTTP 請求,透過 socket 擴展亦可建立長連線的 TCP 伺服器,適用於即時通訊、遊戲伺服器、物聯網裝置通訊等場景。本文示範一個完整的 PHP Socket 伺服器範例,支援多客戶端連線、指令解析(help、quit、shutdown)與基本的錯誤處理。
socket_create(AF_INET, SOCK_STREAM, SOL_TCP)socket_bind() 綁定至 localhost:1337socket_listen($socket, 5) 設定最大等待佇列為 5socket_select() 實現 I/O 多工,同時監聽新連線與現有客戶端資料<?php
set_time_limit(0); // 伺服器長期運行,移除時間限制
$protocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $protocol);
if (!$socket) {
die("socket_create() 失敗:" . socket_strerror(socket_last_error()));
}
$bind = socket_bind($socket, '127.0.0.1', 1337);
if (!$bind) {
die("socket_bind() 失敗:" . socket_strerror(socket_last_error($socket)));
}
$listen = socket_listen($socket, 5);
if (!$listen) {
die("socket_listen() 失敗:" . socket_strerror(socket_last_error($socket)));
}
echo "伺服器啟動,監聽 127.0.0.1:1337\n";
$clients = [$socket]; // 監聽的 socket 陣列
while (true) {
$read = $clients;
$write = $except = null;
// 封鎖等待可讀事件
if (socket_select($read, $write, $except, null) < 1) {
continue;
}
foreach ($read as $sock) {
// 新連線
if ($sock === $socket) {
$client = socket_accept($socket);
if ($client) {
$clients[] = $client;
$welcome = "==========================================\r\n"
. "Welcome to PHP Test Server.\r\n\r\n"
. "指令: quit | shutdown | help\r\n"
. "==========================================\r\nphp> ";
socket_write($client, $welcome, strlen($welcome));
echo "新客戶端連線:" . socket_getpeername($client, $addr, $port) ? "$addr:$port" : "unknown" . "\n";
}
} else {
// 現有客戶端資料
$data = @socket_read($sock, 2048, PHP_BINARY_READ);
if ($data === false || $data === "") {
// 客戶端斷線
$idx = array_search($sock, $clients);
if ($idx !== false) unset($clients[$idx]);
socket_close($sock);
echo "客戶端斷線\n";
continue;
}
$cmd = strtoupper(trim($data));
$response = "";
switch ($cmd) {
case 'QUIT':
case 'Q':
$response = "Bye-Bye\r\n";
socket_write($sock, $response, strlen($response));
$idx = array_search($sock, $clients);
if ($idx !== false) unset($clients[$idx]);
socket_close($sock);
break;
case 'SHUTDOWN':
$response = "Server shutting down...\r\n";
socket_write($sock, $response, strlen($response));
// 關閉所有連線並結束程式
foreach ($clients as $c) {
if ($c !== $socket) socket_close($c);
}
socket_close($socket);
exit(0);
case 'HELP':
case 'H':
$response = "PHP Server Help\r\n"
. " quit / q - 斷開自身連線\r\n"
. " shutdown - 關閉伺服器\r\n"
. " help / h - 顯示此說明\r\nphp> ";
socket_write($sock, $response, strlen($response));
break;
default:
$response = "PHP: unknown command '$cmd'\r\nphp> ";
socket_write($sock, $response, strlen($response));
echo "收到指令:$cmd\n";
}
}
}
}
?>
終端機執行 php server.php 啟動伺服器,另開終端機使用 telnet 127.0.0.1 1337 或 nc 127.0.0.1 1337 連線測試指令。