當前位置: 首頁> 最新文章列表> 在PHP 中創建阻塞式服務器:從socket_create 到socket_set_block

在PHP 中創建阻塞式服務器:從socket_create 到socket_set_block

gitbox 2025-05-26

在PHP 中實現一個基於Socket 的阻塞式服務器,可以幫助我們理解更底層的網絡通信原理。阻塞模式意味著服務器會在讀取或寫入數據前一直等待,直到有數據可以處理或連接已準備好。本文將一步步解析如何使用PHP 的socket擴展,從創建socket 到設置為阻塞模式,並構建一個簡單的阻塞式服務器。

一、準備工作:確保啟用Socket 擴展

首先,確認PHP 環境中啟用了socket 擴展。在php.ini中查找並取消下面這一行的註釋(如果有):

 extension=sockets

使用php -m命令檢查擴展是否啟用:

 php -m | grep sockets

如果能看到sockets ,說明擴展已啟用。

二、使用socket 創建一個TCP 服務器

以下是創建socket 的基本步驟,並逐步介紹每個函數的作用。

1. 創建Socket

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("socket_create() failed: " . socket_strerror(socket_last_error()) . "\n");
}

這裡我們創建的是一個基於IPv4( AF_INET )的TCP socket( SOCK_STREAM )。

2. 設置Socket 選項(可選)

可以設置一些socket 選項,如端口復用:

 socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

3. 綁定Socket

 $host = '0.0.0.0';
$port = 9000;
if (!socket_bind($socket, $host, $port)) {
    die("socket_bind() failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

4. 監聽端口

if (!socket_listen($socket, 5)) {
    die("socket_listen() failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

5表示最多掛起的連接請求數。

三、設置為阻塞模式

使用socket_set_block將socket 設置為阻塞模式。

 if (!socket_set_block($socket)) {
    die("socket_set_block() failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

一旦設置為阻塞模式,後續的socket_acceptsocket_read等函數都會阻塞,直到操作完成。

四、接受連接並讀取數據

echo "服務器已啟動,監聽端口 $port...\n";

while (true) {
    $clientSocket = socket_accept($socket);
    if ($clientSocket === false) {
        echo "socket_accept() failed: " . socket_strerror(socket_last_error($socket)) . "\n";
        continue;
    }

    $input = socket_read($clientSocket, 1024);
    if ($input === false) {
        echo "socket_read() failed: " . socket_strerror(socket_last_error($clientSocket)) . "\n";
    } else {
        $input = trim($input);
        echo "收到消息: $input\n";

        $response = "你發送了:$input\n";
        socket_write($clientSocket, $response, strlen($response));
    }

    socket_close($clientSocket);
}

五、關閉服務器

在需要退出時,別忘了關閉主socket:

 socket_close($socket);

六、訪問測試

你可以使用命令行客戶端如telnet連接測試:

 telnet gitbox.net 9000

或寫一個簡單的PHP 客戶端進行連接測試。

總結

通過socket_createsocket_set_block ,我們構建了一個完整的阻塞式服務器。這個模式適合簡單的網絡通信應用,比如教學、調試或低並發場景。對於高並發場景,建議使用非阻塞模式或搭配select / poll實現更高效的事件循環。

通過本文的實踐步驟,你可以掌握在PHP 中構建阻塞式服務器的全過程,並為進一步深入網絡編程打下堅實基礎。