首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP Socket 伺服器實作:建立 TCP 監聽與互動指令處理

     編輯:PHP 綜合知識

PHP 不僅能處理 HTTP 請求,透過 socket 擴展亦可建立長連線的 TCP 伺服器,適用於即時通訊、遊戲伺服器、物聯網裝置通訊等場景。本文示範一個完整的 PHP Socket 伺服器範例,支援多客戶端連線、指令解析(help、quit、shutdown)與基本的錯誤處理。

程式架構說明

  1. 建立 Socket:socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
  2. 綁定 IP 與 Port:socket_bind() 綁定至 localhost:1337
  3. 進入監聽狀態:socket_listen($socket, 5) 設定最大等待佇列為 5
  4. 主迴圈:使用 socket_select() 實現 I/O 多工,同時監聽新連線與現有客戶端資料
  5. 指令處理:解析客戶端傳入字串,回應對應訊息

完整程式碼

<?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 連線測試指令。

生產環境建議

  • 使用 pcntl_fork() 或 pthreads 實現多進程/多執行緒處理高併發。
  • 加入 SSL/TLS 加密(stream_socket_enable_crypto())。
  • 實作心跳機制偵測死連線。
  • 考慮使用成熟框架如 Workerman、Swoole 以獲得更佳效能與穩定性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved