WebSocket 非同步風格伺服器 WebSocket\Server 繼承自 Http\Server,所以 Http\Server 提供的所有 API 和配置項都可以使用。 # ws_server.php class WebSocket { public $server; public functi ...
WebSocket 非同步風格伺服器
WebSocket\Server
繼承自 Http\Server,所以 Http\Server
提供的所有 API
和配置項都可以使用。
# ws_server.php
class WebSocket
{
public $server;
public function __construct()
{
// 創建websocket伺服器對象,監聽0.0.0.0:9502埠
$this->server = new Swoole\WebSocket\Server("0.0.0.0", 9502);
// 設置伺服器運行參數
$serv->set(array(
'daemonize' => 1, // 作為守護進程運行,需同時設置log_file
'log_file' => '/www/logs/swoole.log', // 指定標準輸出和錯誤日誌文件
));
// 監聽WebSocket連接打開事件
$this->server->on('open', function ($ws, $request) {
var_dump($request->fd, $request->get, $request->server);
$ws->push($request->fd, "hello, welcome\n");
});
// 監聽WebSocket消息事件
$this->server->on('message', function ($ws, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$ws->push($frame->fd, "server: {$frame->data}");
});
// 監聽WebSocket連接關閉事件
$this->server->on('close', function ($ws, $fd) {
echo "client {$fd} is closed\n";
});
// 通過 HTTP 請求向所有用戶推送消息
$this->server->on('request', function ($request, $response) {
foreach ($this->server->connections as $fd) {
// 檢查連接是否為有效的 WebSocket 客戶端連接,避免push失敗
if ($this->server->isEstablished($fd)) {
$this->server->push($fd, $request->get['message']);
}
}
});
$this->server->start();
}
}
// 啟動 WebSocket 伺服器
new WebSocket();
運行並測試 WebSocket 非同步風格伺服器
# 如果程式已經運行,先結束進程
kill -9 11591
# 在 cli 命令行環境運行服務端
php ws_server.php
# 查看伺服器監聽的埠
netstat -an | grep 9502
WebSocket JS客戶端
# index.js
var wsServer = 'ws://127.0.0.1:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
websocket.send('hello ws!');
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
客戶端
Chrome/Firefox/
高版本IE/Safari
等瀏覽器內置了JS
語言的WebSocket
客戶端- 微信小程式開發框架內置的
WebSocket
客戶端 - 非同步 IO 的
PHP
程式中可以使用 Swoole\Coroutine\Http 作為WebSocket
客戶端 Apache/PHP-FPM
或其他同步阻塞的PHP
程式中可以使用swoole/framework
提供的同步 WebSocket 客戶端- 非
WebSocket
客戶端不能與WebSocket
伺服器通信
WebSocket 協程風格伺服器
Co\run(function () {
$server = new Co\Http\Server("127.0.0.1", 9502, false);
$server->handle('/websocket', function ($request, $ws) {
// 向客戶端發送 WebSocket 握手消息
$ws->upgrade();
// 迴圈處理消息的接收和發送
while (true) {
// 接收 WebSocket 消息幀,會掛起當前協程,等待數據到來時再恢復協程的執行
$frame = $ws->recv();
if ($frame === false) {
echo "error : " . swoole_last_error() . "\n";
break;
} else if ($frame == '') {
break;
} else {
if ($frame->data == "close") {
$ws->close();
return;
}
// 向對端發送數據幀
$ws->push("Hello {$frame->data}!");
$ws->push("How are you, {$frame->data}?");
}
}
});
$server->handle('/', function ($request, $response) {
$response->end(<<<HTML
<h1>Swoole WebSocket Server</h1>
<script>
var wsServer = 'ws://127.0.0.1:9502/websocket';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
websocket.send('hello');
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
</script>
HTML
);
});
$server->start();
});