PHP Socket 編程資料稀缺;真正難點在於 Flash Player 安全沙箱——特別是 FP10+ 強制要求 Socket 連接前下發跨域策略文件。
<policy-file-request/>\0 結束<?php
set_time_limit(0);
$address = "127.0.0.1";
$port = 8083;
ob_implicit_flush();
// 創建 Socket
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
die("socket_create failed: " . socket_strerror($sock));
}
if (($ret = socket_bind($sock, $address, $port)) < 0) {
die("socket_bind failed: " . socket_strerror($ret));
}
if (($ret = socket_listen($sock, 5)) < 0) {
die("socket_listen failed: " . socket_strerror($ret));
}
do {
if (!($msgsock = socket_accept($sock))) {
echo "socket_accept failed\n";
break;
}
do {
if ($buf = socket_read($msgsock, 2048)) {
// 處理策略文件請求
if (strpos($buf, 'policy-file-request') !== false) {
$policy = "<cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>";
socket_write($msgsock, $policy . "\0", strlen($policy . "\0"));
continue;
}
// 正常業務回應
$talkback = "PHP: You said '$buf'.\n";
socket_write($msgsock, $talkback, strlen($talkback));
}
} while (true);
socket_close($msgsock);
} while (true);
?>
| 要點 | 說明 |
|---|---|
set_time_limit(0) | 移除腳本執行時間限制,長連接必需 |
ob_implicit_flush() | 隱式刷新輸出緩衝,實時發送 |
| 策略文件格式 | XML 格式,domain='*' 允許所有域,to-ports='*' 允許所有端口 |
\0 結束符 | Flash 要求策略文件以空字節結束 |
socket_read($msgsock, 2048) | 讀取客戶端數據,緩衝區大小可調 |
// ActionScript 3
var socket:Socket = new Socket();
socket.connect("127.0.0.1", 8083);
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(DataEvent.DATA, onData);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
若遇到 SecurityError #2048,必為策略文件未正確下發或格式錯誤。建議使用 Wireshark 抓包分析握手過程。
若非必須用 PHP,Node.js、Python、Java、Go 等語言的 Socket 生態更成熟,開發效率與穩定性更高。PHP 適合簡單場景或受限於技術棧統一要求時使用。