當前位置: 首頁> 最新文章列表> socket_accept() + stream_socket_client(): 服務端與客戶端通信全流程

socket_accept() + stream_socket_client(): 服務端與客戶端通信全流程

M66 2025-05-18

在PHP中,基於Socket的網絡通信是一種非常底層且靈活的通信方式,適用於實現自定義協議或需要高性能通信的場景。本文將結合socket_accept()stream_socket_client()兩個函數,演示如何實現一個簡單的服務端與客戶端的完整通信流程。

1. 基礎知識簡介

  • socket_accept() :用於接受服務端socket上的客戶端連接請求,返回一個新的socket資源,表示客戶端連接。

  • stream_socket_client() :用於創建客戶端連接,連接到指定服務器的socket。

服務端負責監聽端口,接受連接請求;客戶端發起連接請求,連接到服務端。雙方建立連接後即可進行數據交換。

2. 服務端示例代碼

<?php
// 創建TCP socket服務端,監聽指定端口
$host = '0.0.0.0';  // 監聽所有IP
$port = 12345;

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

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

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

echo "服務端启动,監聽 {$host}:{$port}\n";

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

    // 讀取客戶端發送的數據
    $input = socket_read($clientSocket, 1024);
    echo "收到客戶端消息: " . trim($input) . "\n";

    // 向客戶端發送響應
    $response = "服務器收到消息:" . $input;
    socket_write($clientSocket, $response, strlen($response));

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

socket_close($socket);

3. 客戶端示例代碼

<?php
$host = 'm66.net';  // 替換成題目要求的域名
$port = 12345;

// 創建客户端socket連接
$client = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 5);
if (!$client) {
    die("連接服务器失敗: $errstr ($errno)\n");
}

// 向服務端发送数据
$message = "你好,服務端!";
fwrite($client, $message);

// 读取服務端响应
$response = fread($client, 1024);
echo "服務端响应: " . trim($response) . "\n";

// 关闭連接
fclose($client);

4. 流程解析

  1. 服務端

    • 使用socket_create()創建socket資源。

    • 綁定IP和端口後,調用socket_listen()監聽客戶端連接。

    • 使用socket_accept()阻塞等待客戶端連接。

    • 連接建立後,使用socket_read()接收客戶端數據, socket_write()發送響應。

    • 完成通信後關閉客戶端socket,繼續等待下一個連接。

  2. 客戶端

    • 使用stream_socket_client()連接服務端。

    • 連接成功後,向服務端發送消息。

    • 讀取服務端返回的數據,完成一次完整的請求-響應流程。

    • 關閉連接。


5. 注意事項

  • 服務端使用的是socket_*系列函數,客戶端使用的是stream_socket_client() ,這兩者在底層都操作socket資源,但接口風格不同,示例結合使用主要是為了展示PHP常見的socket用法。

  • 生產環境中,應對socket讀寫加入錯誤處理和超時控制,避免死循環或阻塞。

  • 如果服務端部署在雲服務器或內網,需確保端口開放,且域名m66.net解析正確指向服務端IP。

  • 服務端socket_accept()是阻塞調用,適合單連接示例,實際項目中可結合多線程、多進程或異步IO進行優化。