Socket 是網路通訊的基礎抽象,PHP 透過 `ext-sockets` 擴充提供 Berkeley Socket API 的大部分功能。雖然現代開發多使用 HTTP API、WebSocket 或 gRPC,但理解 Socket 底層運作對排查網路問題、開發自訂協議、高效能長連線服務仍具關鍵價值。
建立 Socket 需指定三個參數:
| 類別 | 常用常數 | 說明 |
|---|---|---|
| 通訊域 | AF_INET (IPv4), AF_INET6 (IPv6), AF_UNIX (本機) | 決定位址格式與傳輸範圍 |
| Socket 型態 | SOCK_STREAM (TCP, 可靠串流), SOCK_DGRAM (UDP, 無連線) | 決定傳輸語意 |
| 協定 | SOL_TCP, SOL_UDP, SOL_ICMP | 具體協定編號,通常由型態推導 |
<?php
// 1. 建立 Socket 資源
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) die("socket_create 失敗: " . socket_strerror(socket_last_error()));
// 2. 綁定 IP 與 Port
if (!socket_bind($socket, '0.0.0.0', 1337)) {
die("socket_bind 失敗: " . socket_strerror(socket_last_error($socket)));
}
// 3. 開始監聽(backlog 512 為常見預設)
if (!socket_listen($socket, 512)) {
die("socket_listen 失敗: " . socket_strerror(socket_last_error($socket)));
}
echo "Server 啟動,監聽 0.0.0.0:1337\n";
// 4. 事件迴圈(單執行緒阻塞示範)
while (true) {
// 接受連線(阻塞直到有客戶端連入)
$client = socket_accept($socket);
if ($client === false) {
echo "socket_accept 失敗: " . socket_strerror(socket_last_error($socket)) . "\n";
continue;
}
$peer = socket_getpeername($client, $addr, $port);
echo "新連線來自 $addr:$port\n";
// 讀取資料(阻塞直到有資料或連線關閉)
$data = socket_read($client, 4096, PHP_NORMAL_READ);
if ($data === false) {
echo "讀取錯誤: " . socket_strerror(socket_last_error($client)) . "\n";
} else {
echo "收到: $data\n";
// 回應
$resp = "Server 收到: $data\n";
socket_write($client, $resp, strlen($resp));
}
socket_close($client);
}
// 永不執行到此,實際專案需訊號處理優雅關閉
socket_close($socket);
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) die("建立失敗");
$result = socket_connect($socket, '127.0.0.1', 1337);
if ($result === false) die("連線失敗: " . socket_strerror(socket_last_error($socket)));
$msg = "Hello from PHP Client!\n";
socket_write($socket, $msg, strlen($msg));
$reply = socket_read($socket, 4096, PHP_NORMAL_READ);
echo "Server 回應: $reply";
socket_close($socket);
| 函式 | 用途 |
|---|---|
socket_create | 建立 socket 資源 |
socket_bind | 綁定本地 IP:Port |
socket_listen | 轉為被動監聽狀態 |
socket_accept | 接受連線,返回新 socket |
socket_connect | 主動發起連線 |
socket_read | 讀取資料(支援長度/換行模式) |
socket_write | 寫入資料(可能需迴圈確保全寫入) |
socket_close | 關閉 socket 釋放資源 |
socket_select | I/O 多工(非阻塞/並發核心) |
socket_set_nonblock | 設定非阻塞模式 |
socket_getpeername | 取得對端 IP:Port |
socket_last_error / socket_strerror | 錯誤處理 |
單執行緒阻塞模型一次只能服務一個客戶端。生產環境常見方案:
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);Socket 是網路程式設計的基石。掌握 `socket_create/bind/listen/accept/read/write/close` 核心流程、理解阻塞與非阻塞模型、熟悉 `socket_select` 多工機制,即能在需要時突破 HTTP 框架限制,構建高效能、自訂協議的網路服務。