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

PHP 多進程編程實戰:基於 pcntl + socket 實現 VNC 代理守護進程

     編輯:PHP 相關知識

本文提供一個完整的 PHP 多進程示例,結合 pcntl_fork、信號處理與非阻塞 Socket,實現一個將外部連接轉發至內部 VNC 服務的守護進程。代碼涵蓋進程分離、信號捕獲、雙向數據透傳、資源清理等核心環節,可作為 PHP CLI 多進程網絡編程的參考模板。

核心架構

  • 主進程:綁定監聽端口(默認 9999),循環 accept 連接,fork 子進程處理,自身持續監聽。
  • 子進程:連接目標 VNC(192.168.1.1:5900),雙向非阻塞讀寫轉發數據。
  • 信號機制:SIGTERM/SIGTRAP 優雅關閉,SIGCHLD 回收子進程避免殭屍。

關鍵代碼片段

1. 守護進程初始化

$pid = pcntl_fork();
if ($pid == -1) die("could not fork");
if ($pid) die("Daemon PID:$pid\n"); // 父進程退出,子進程成為孤兒進程由 init 收養

if (!posix_setsid()) die("could not detach from terminal\n"); // 脫離終端

declare(ticks = 1); // 必須開啟才能註冊信號處理器
pcntl_signal(SIGTERM, "SignalFunction");
pcntl_signal(SIGTRAP, "SignalFunction");
pcntl_signal(SIGCHLD, "SignalFunction");

2. 主進程監聽循環

$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, 0, $ServerPort); // 0 監聽所有接口
socket_listen($serverSocket);
socket_set_nonblock($serverSocket); // 非阻塞

unset($PID); // 標記無活躍子進程

while (true) {
    sleep(1); // 輪詢間隔
    $connected = @socket_accept($serverSocket);
    if ($connected !== false) {
        $PID = pcntl_fork();
        if ($PID == -1) die("could not fork");
        if ($PID) continue; // 父進程繼續監聽

        // 子進程處理連接
        ProcessSocket($connected);
        DestroySocket();
        exit(0);
    }
}

3. 子進程雙向轉發邏輯

function ProcessSocket($serverSocket) {
    global $RemoteSocket, $IP, $Port;
    declare(ticks = 1);
    pcntl_signal(SIGTERM, "ChildSignalFunction");
    pcntl_signal(SIGTRAP, "ChildSignalFunction");

    $RemoteSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    @socket_connect($RemoteSocket, $IP, $Port);
    socket_set_nonblock($RemoteSocket);
    socket_set_nonblock($serverSocket);

    while (true) {
        $recv = @socket_read($serverSocket, 4096, PHP_BINARY_READ);
        $remoteRecv = @socket_read($RemoteSocket, 4096, PHP_BINARY_READ);

        // 處理斷開、無數據、數據轉發邏輯...
        // 關鍵:非阻塞模式下 false 表示無數據,'' 表示連接關閉
        // 使用 usleep(100000) 避免空轉佔用 CPU
    }
}

4. 資源清理與信號處理

function DestroySocket() {
    global $ServerSocket, $RemoteSocket;
    if ($RemoteSocket) {
        @socket_shutdown($RemoteSocket, 2);
        socket_clear_error($RemoteSocket);
        socket_close($RemoteSocket);
    }
    @socket_shutdown($ServerSocket, 2);
    socket_clear_error($ServerSocket);
    socket_close($ServerSocket);
}

function SignalFunction($sig) {
    global $PID;
    switch ($sig) {
        case SIGTERM: case SIGTRAP:
            if ($PID) { posix_kill($PID, SIGTERM); pcntl_wait($status); }
            DestroySocket(); exit(0);
        case SIGCHLD:
            unset($PID); pcntl_wait($status); break;
    }
}

部署提示

  • 需啟用 pcntl、sockets 擴展(僅 CLI 模式可用)。
  • 生產環境建議使用 Supervisor 等進程管理工具托管守護進程。
  • 此模型可擴展為通用 TCP 代理、負載均衡器等場景。

完整代碼已包含錯誤處理、非阻塞輪詢、優雅關閉等工程化細節,可直接作為 PHP 多進程網絡編程的起點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved