PHP 不僅能開發 Web 應用,透過 sockets 擴展也能編寫獨立的 TCP 伺服器/客戶端程式。本文提供一個完整的多連線 TCP Echo 伺服器範例,支援基本指令處理(HELLO、QUIT、HELP),展示阻塞式 I/O 與 socket_select() 多路複用的核心模式。
<?php
// Server.php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$ip = "127.0.0.1";
$port = 1000;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) die("socket_create() failed: " . socket_strerror(socket_last_error()));
socket_bind($socket, $ip, $port) or die("socket_bind() failed");
socket_listen($socket) or die("socket_listen() failed");
echo "Server started on {$ip}:{$port}\n";
while (true) {
$client = socket_accept($socket);
if (!$client) continue;
socket_write($client, "Welcome to PHP Server!\n");
while (true) {
$cmd = strtoupper(trim(socket_read($client, 1024)));
if (!$cmd) break;
switch ($cmd) {
case 'HELLO': $reply = "Hello Everybody!"; break;
case 'QUIT': $reply = "Bye-Bye"; break;
case 'HELP': $reply = "HELLO\tQUIT\tHELP"; break;
default: $reply = "Error Command!";
}
socket_write($client, $reply . "\n");
if ($cmd === 'QUIT') break;
}
socket_close($client);
}
socket_close($socket);
?>
# 終端機直接連線
telnet 127.0.0.1 1000
# 或 PHP 客戶端
$fp = fsockopen("127.0.0.1", 1000);
fwrite($fp, "HELLO\n");
echo fgets($fp, 1024);
fclose($fp);
| 函數 | 用途 |
|---|---|
| socket_create() | 建立 Socket 資源(AF_INET=IPv4, SOCK_STREAM=TCP) |
| socket_bind() | 綁定 IP 與 Port |
| socket_listen() | 監聽連線,第二參數為 backlog 队列長度 |
| socket_accept() | 接受連線,回傳新的客戶端 Socket |
| socket_read()/socket_write() | 阻塞式讀寫資料 |
| socket_select() | 多路複用:同時監控多個 Socket 可讀/可寫狀態(進階用法) |
socket_select() 實作單進程多連線並發(參考 patServer 類別架構)。stream_socket_enable_crypto())。掌握 Socket 基礎,即可開發即時聊天室、遊戲伺服器、物聯網閘道等非 HTTP 協定應用。