Реализация чата на сайте
Пишу для сайта чат не большой и с толкнулся с проблемой как правильно построить опрос на предмет новых сообщений. Проблемы заключаются вот в чем:
Если опрос делать бесконесным циклом while(true) и использовать sleep(1) то если каждый раз когда обновляешь страницу происходит долгая обработка данных. Конечно session_write_close() не много помогает НО не для всех ПК... то есть если ПК слабый то результат ровным счетом не меняется мы остаемся так же с долгой загрузкой.
Опрос делать к примеру раз в секунду к БД с помощью ajax и тут я так понимаю будет нагрузка идти на БД от частых запросов.
И сам вопрос как правильно реализовать опрос на предмет новых сообщений что бы это не нагружало системы как у клиента так же и самого сервака?
UPD:
Скажите пожалуйста на сколько хороша такая реализация?
на странице index.html/php делаем ajax запрос на страницу ... ну пускай будет эта страница просто page.php
index.html/php
<script>
// (B) LAST UPDATED TIMESTAMP
var last = 0;
// (C) AJAX LONG POLL
function poll () {
// (C1) FORM DATA
let data = new FormData();
data.append("last", last);
// (C2) FETCH
console.log("Fetch run");
fetch("page.php", { method:"POST", body:data })
.then((res) => { return res.json(); })
// (C3) UPDATE ON SERVER RESPONSE
.then((data) => {
// HTML DISPLAY
let sb = document.getElementById("scoreboard");
sb.innerHTML = `[${data.time}] ${data.home} - ${data.away}`;
// NEXT ROUND
last = data.unix;
poll();
})
// (C4) CATCH ERROR - LOOP ON TIMEOUT
.catch((err) => { poll(); });
}
// (D) GO!
window.addEventListener("DOMContentLoaded", poll);
</script>
page.php
<?php
// (A) TIME LIMIT & ABORT
set_time_limit(30); // SET THE APPROPRIATE TIME LIMIT
ignore_user_abort(false); // STOP WHEN LONG POLLING BREAKS
// (B) DATABASE SETTINGS - CHANGE THESE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHAR", "utf8");
define("DB_USER", "root");
define("DB_PASS", "");
// (C) DATABASE CLASS
class DB {
// (C1) CONSTRUCTOR - CONNECT TO DATABASE
protected $pdo = null;
protected $stmt = null;
function __construct () {
try {
$this->pdo = new PDO(
"mysql:host=".DB_HOST.";charset=".DB_CHAR.";dbname=".DB_NAME,
DB_USER, DB_PASS
);
} catch (Exception $ex) { exit($ex->getMessage()); }
}
// (C2) DESTRUCTOR - CLOSE CONNECTION
function __destruct () {
if ($this->stmt !== null) { $this->stmt = null; }
if ($this->pdo !== null) { $this->pdo = null; }
}
// (C3) GET LATEST SCORE
function getScore () {
$this->stmt = $this->pdo->prepare(
"SELECT *, UNIX_TIMESTAMP(`time`) AS `unix`
FROM `score` ORDER BY `time` DESC LIMIT 1"
);
$this->stmt->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
}
$DB = new DB();
// (D) LOOP - CHECK FOR SCORE UPDATES
// WILL KEEP LOOPING UNTIL A SCORE UPDATE OR TIMEOUT
if (isset($_POST["last"])) { while (true) {
$score = $DB->getScore();
if (isset($score["unix"]) && $score["unix"] > $_POST["last"]) {
echo json_encode($score);
break;
}
sleep(1); // NOT TO BREAK THE SERVER. SHORT PAUSE BEFORE NEXT CHECK.
}}
Этот пример я нашел на одном из сайтов вот только бы понять на сколько хорош это вариант
Подскажите пожалуйста по следующему моменту: Я знаю что на C# есть такая тема что если объявить какую то переменную ну для примера пускай будет $show = false; (И тут сразу скажу что точно сейчас не помню как правильно на C# задаются переменные это чисто для примера) и при нажатии кнопки одного из пользователя задать этой переменной значение true то у всех пользователей значение переменной $show станет true. Возможно ли такое сделать и на PHP?