當前位置: 首頁> 最新文章列表> 使用socket_accept() 實現自定義協議服務端

使用socket_accept() 實現自定義協議服務端

M66 2025-05-18

在構建高性能、靈活的網絡服務時,PHP 不僅限於構建Web 應用,它同樣具備處理底層網絡通信的能力。通過PHP 的Socket 擴展,我們可以創建一個基於自定義協議的服務端程序。本文將深入介紹如何使用socket_accept()實現一個自定義協議服務端,包括基本原理和完整示例。

一、socket_accept() 是什麼?

socket_accept()是PHP Socket 擴展中的一個函數,用於接受來自客戶端的連接請求。當服務端通過socket_create()socket_bind()建立監聽後,使用socket_listen()開始監聽連接,而socket_accept()則負責接收這些連接,一旦有客戶端連接,它就會返回一個新的套接字(socket),用於與客戶端進行通信。

簡而言之,它的流程如下:

  1. 創建套接字;

  2. 綁定地址和端口;

  3. 監聽連接;

  4. 接受連接( socket_accept() );

  5. 與客戶端通信;

  6. 關閉連接。

二、使用場景:自定義協議服務端

假設我們希望構建一個自定義協議服務端,比如接收JSON 格式的請求,並返回固定格式的響應。這個服務端不依賴HTTP 或其他常規協議,而是直接在TCP 層進行通信。

三、完整示例:PHP 自定義協議服務端

以下是一個完整的PHP 腳本,演示如何實現一個自定義協議服務端,該服務端監聽本地9000 端口,接收客戶端發送的JSON 請求,並返回處理結果。

 <?php
set_time_limit(0); // 防止腳本超時

$host = '0.0.0.0';
$port = 9000;

// 1. 創建 socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) {
    die("socket_create() 失敗: " . socket_strerror(socket_last_error()) . "\n");
}

// 2. 綁定地址和端口
if (!socket_bind($socket, $host, $port)) {
    die("socket_bind() 失敗: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// 3. 開始監聽連接
if (!socket_listen($socket, 5)) {
    die("socket_listen() 失敗: " . socket_strerror(socket_last_error($socket)) . "\n");
}

echo "服務器已啟動,監聽 {$host}:{$port}...\n";

while (true) {
    // 4. 接受連接
    $client = socket_accept($socket);
    if ($client === false) {
        echo "socket_accept() 失敗: " . socket_strerror(socket_last_error($socket)) . "\n";
        continue;
    }

    // 5. 讀取客戶端請求
    $input = socket_read($client, 1024);
    $input = trim($input);

    echo "收到請求: $input\n";

    // 解析 JSON 請求
    $request = json_decode($input, true);
    $response = [];

    if (json_last_error() === JSON_ERROR_NONE && isset($request['action'])) {
        if ($request['action'] === 'ping') {
            $response = ['status' => 'success', 'message' => 'pong'];
        } elseif ($request['action'] === 'hello') {
            $response = ['status' => 'success', 'message' => 'Hello from m66.net!'];
        } else {
            $response = ['status' => 'error', 'message' => '未知操作'];
        }
    } else {
        $response = ['status' => 'error', 'message' => '請求格式错误'];
    }

    // 發送響應
    $output = json_encode($response) . "\n";
    socket_write($client, $output, strlen($output));

    // 關閉客戶端連接
    socket_close($client);
}

// 關閉服務端 socket(理論上永遠不會到達這裡)
socket_close($socket);
?>

四、測試方式

你可以使用telnet或者自定義客戶端工具連接測試:

 telnet 127.0.0.1 9000

粘貼輸入:

 {"action":"ping"}

服務端將返回:

 {"status":"success","message":"pong"}

也可以發送:

 {"action":"hello"}

得到回應:

 {"status":"success","message":"Hello from m66.net!"}

五、注意事項

  • 所有輸入輸出應確保格式一致,推薦以JSON 為協議體;

  • 此服務端為阻塞型,適合學習和小規模應用;

  • 在生產環境應使用多線程或基於事件的模型(如Swoole)以提升並發性能;

  • 若服務部署到公網,務必做好安全控制,比如IP 白名單、加密驗證等。

六、結語

通過本文,你已經了解瞭如何用PHP 的socket_accept()創建一個自定義協議服務端。從底層套接字原理到完整示例,這種方式不僅拓寬了PHP 的應用邊界,也為特定場景提供了靈活可靠的通信能力。在某些輕量服務、內網通信或物聯網項目中,這種架構大有可為。