I have a Ratchet server and chat app class which runs fine. My problem is how do I add a periodic loop?
I tried to follow the example in Periodically sending mesages to clients in Ratchet
But I have been getting nowhere. My goal like this guy, is for the server to check all clients are still alive. Everytime I try to use the addPeriodicTimer, I cant seem to access the $clients public property in chat.php like the guy from the link above could in order to send messages from the timer in server.php. The foreach loop in the periodic timer in server.php keeps complaining that it apparently has an "invalid argument".
Can anyone see what im doing wrong?
my server.php code:
<?php
require($_SERVER['DOCUMENT_ROOT'].'/var/www/html/vendor/autoload.php');
require_once($_SERVER['DOCUMENT_ROOT']."/var/www/html/bin/chat.php");
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ram\Chat;
$server = IoServer::factory(new HttpServer(new WsServer(new Chat())), 8080);
// Server timer <------ having trouble here
$server->loop->addPeriodicTimer(5, function () use ($server) {
foreach($server->app->clients as $client)
{
//$client->send("[helloworld]");
}
});
$server->run();
?>
and my chat.php:
<?php
namespace Ram;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
error_reporting(E_ALL ^ E_NOTICE);
session_id($_GET['sessid']);
if(!session_id)
session_start();
$userid = $_SESSION["userid"];
$username = $_SESSION["username"];
$isadmin = $_SESSION["isadmin"];
$resources = array();
class Users
{
public $name;
public $resid;
public $timestamp;
}
class Chat implements MessageComponentInterface
{
public $clients;
var $users = array();
/*
function cmp($a, $b)
{
return strcmp($a->name, $b->name);
}
function removeObjectById(ConnectionInterface $id , $arr)
{
$array = $arr;
foreach ( $array as $key => $element ) {
if ( $id->resourceId == $element->resid )
{
unset($array[$key]);
break;
}
}
usort($array, "cmp");
return $array;
}
*/
public function __construct()
{
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
}
public function onClose(ConnectionInterface $conn)
{
//$users = removeObjectById($conn, $users);
$this->clients->detach($conn);
}
public function onMessage(ConnectionInterface $conn, $msg)
{
$msgjson = json_decode($msg);
$tag = $msgjson->tag;
if($tag == "[msgsend]")
{
foreach($this->clients as $client)
{
$client->send($msg);
}
}
else if($tag == "[bye]")
{
foreach($this->clients as $client)
{
$client->send($msg);
}
$this->clients->detach($conn);
}
else if($tag == "[connected]")
{
//store client information
$temp = new Users();
$temp->name = $msgjson->uname;
$temp->resid = $conn->resourceId;
$temp->timestamp = date('Y-m-d H:i:s');
$users[] = $temp;
//usort($users, "cmp");
//send out messages
foreach($this->clients as $client)
{
$client->send($msg);
}
}
else if($tag == "[imalive]")
{
//update user timestamp who sent [imalive]
if (is_array($users) || is_object($users))
{
foreach($users as $user)
{
if($msgjson->uname == $user->name)
{
$user->timestamp = date('Y-m-d H:i:s');
}
}
}
}
}
public function onError(ConnectionInterface $conn, Exception $e)
{
echo "Error: " . $e->getMessage();
$conn -> close();
}
}
?>
Why not define the Chat
object instance before passing into HTTPServer
:
$chat = new Chat();
$server = IoServer::factory(new HttpServer(new WsServer($chat)), 8080);
// Server timer <------ having trouble here
$server->loop->addPeriodicTimer(5, function () use ($chat) {
foreach($chat->clients as $client)
{
//$client->send("[helloworld]");
}
});
$server->run();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With