一直不能下決心好好學習,仔細研究一下,決定用盡量降低難度曲線的方法,從易到難,一步一步的學習,所以整了個demo專案。
git倉庫和使用步驟
確保能看到swoole,在 php -m 命令中
php -m
git clone https://github.com/lang123789/swoole_demo.git
然後設定了標籤,本文對應 v5.0
cd swoole_demo
git checkout v5.0
有提示錯誤之類,但程式碼已經切換到 v5.0 了。
## 安裝類庫,生成 autoload.php 檔案
composer install
## 啟動 websocket 服務
php src/WebSocket/run.php
需求
9、加入心跳功能,確保使用者不輸入的情況下,只要頁面開啟,則應該長連線保持。
測試網址
主要程式碼
客戶端主要程式碼
客戶端程式碼主要在 index.php 中
window.onload = function() {
activate_chat_js();
var wsServer = 'ws://{$JS_IP}:9501';
var websocket = new WebSocket(wsServer);
window.websocket = websocket;
websocket.onopen = function(evt) {
console.log("Connected to WebSocket server.");
heartCheck.reset().start(); //心跳檢測重置
websocket.send("my_id|{$user_id}");
};
websocket.onclose = function(evt) {
console.log("Disconnected");
};
websocket.onmessage = function(evt) {
console.log('從伺服器接受的資料 ' + evt.data);
// 心跳最前面檢測
if (evt.data == 'pong') {
heartCheck.reset().start(); //心跳檢測重置
return;
}
var user = JSON.parse(evt.data);
if (user.type == 'my_id') {
system_chatWindow(user.message);
}
// v4.0修改。其他人接受某人的訊息廣播。
if (user.type == 'my_message') {
update_chatWindow2(user.message, user.from_user_name);
}
};
websocket.onerror = function(evt, e) {
console.log('Error occured: ' + evt.data);
};
var heartCheck = {
timeout: 5000,
//單位毫秒,5秒發一次心跳,改成61000,就是61秒就會被伺服器自動斷掉,
// 說明,只需這個值大於 伺服器的heartbeat_idle_time 與 heartbeat_check_interval 的和,就一定會自動停掉。
timeoutObj: null,
serverTimeoutObj: null,
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function() {
var self = this;
this.timeoutObj = setTimeout(function() {
//這裡傳送一個心跳,後端收到後,返回一個心跳訊息,
//onmessage拿到返回的心跳就說明連線正常
websocket.send("ping");
console.log("ping")
}, this.timeout)
}
};
}
服務端主要程式碼
$this->server = new \swoole_websocket_server(
$this->config['socket']['host'],
$this->config['socket']['port']
);
//v5.0 設定心跳檢測
$this->server->set(array(
'heartbeat_idle_time' => 30, // 表示一個連線如果30秒內未向伺服器傳送任何資料,此連線將被強制關閉
'heartbeat_check_interval' => 25, // 表示每25秒遍歷一次
));
public function message(\swoole_websocket_server $server, \swoole_websocket_frame $frame) {
$data = $frame->data;
echo "有訊息:".$data."\n";
//這裡使用者發來的資訊已經分型別了。my_id開頭,說明是系統自動從客戶端傳送的資訊,用於識別身份。
if (preg_match('#^ping#', $data)) {
echo "心跳來了 " .date("Y-m-d H:i:s")."\n";
$server->push($frame->fd,'pong');// 返回一個訊息,過會他會再次傳來。
} elseif (preg_match('#^my_id#', $data)) {
$user_id = explode("|", $data)[1];
$arr = $this->user_all;
$user_name = isset($arr[$user_id]) ? $arr[$user_id] : '';
//。。。。。
}
}
WebSocketServer.php 是核心檔案。
程式碼說明
1、客戶端每隔多少秒傳送一次訊息給伺服器,防止伺服器斷長連線。
2、只需這個值大於 伺服器的heartbeat_idle_time 與 heartbeat_check_interval 的和,就一定會自動停掉。
3、保險起見,客戶端的定時的值,需要小於heartbeat_idle_time 值。
4、heartbeat_idle_time 表示伺服器發現某客戶端多長時間不聯絡伺服器,就主動斷
5、heartbeat_check_interval 表示伺服器每隔多長時間來檢測這個心跳。顯然應小於heartbeat_idle_time
6、客戶端在 onopen 和 onmessage 這兩個方法裡進行定時器設定,具體象打乒乓球,客戶端發出ping,伺服器立刻返回,客戶端間隔一定時間,再次ping,伺服器總是立刻返回。
本作品採用《CC 協議》,轉載必須註明作者和本文連結