我的服务器有方法SendToAll($ message)。我需要单独的线程,每秒都会运行此方法(SendToAll)。我正在使用pthreads。
class Sender extends Thread
{
public function __construct($server)
{
$this->server = $server;
}
public function run()
{
for (;;) {
$this->server->SendForAll("Hello");
sleep(1);
}
}
}
}
我创建服务器的对象并尝试将其放入发件人的构造中。
<?php
require_once('includes.php');
runServer();
function runServer()
{
$server = new WssService("0.0.0.0", 9001);
$asyncOp = new Sender($server);
try {
$asyncOp->start();
$server->StartServer();
}catch (Exception $e) {
echo $e->getMessage();
runServer();
}
}
但我有错误
Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Clos
ure' is not allowed' in D:\xampp\htdocs\admin_p\classes\AsyncStorage.php:6
Stack trace:
#0 D:\xampp\htdocs\admin_p\classes\AsyncStorage.php(6): Sender::__construct()
#1 D:\xampp\htdocs\admin_p\ss.php(9): Sender->__construct(Object(WssService))
#2 D:\xampp\htdocs\admin_p\ss.php(4): runServer()
#3 {main}
thrown in D:\xampp\htdocs\admin_p\classes\AsyncStorage.php on line 6
P.S。对不起,英语 - 这不是我的母语。
class WssService
{
public $connects_storage = array();
private $server = null;
private $logger = null;
private $writer = null;
public $loop = null;
public function __construct($URI, $port)
{
$this->connected_users = array();
$this->loop = \React\EventLoop\Factory::create();
$this->Logger = new \Zend\Log\Logger();
$this->writer = new Zend\Log\Writer\Stream("php://output");
$this->Logger->addWriter($this->writer);
$this->server = new WebSocketServer("tcp://" . $URI . ":" . $port, $this->loop, $this->Logger);
$this->server->on("connect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Connected " . $user->getIp()));
array_push($this->connects_storage,$user);
});
$this->server->on("disconnect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Disconnected " . $user->getIp()));
});
$this->server->on("message", function (WebSocketTransportInterface $s_user, WebSocketMessageInterface $message) {
$s_user->sendString($message);
});
}
public function StartServer(){
$this->server->bind();
$this->loop->run();
}
public function SendForAll($message){
foreach($this->connects_storage as $client){
$client->sendString($message);
}
}
}
更新方法SendForAll()
public function SendForAll($message){
echo var_export($message,true) .PHP_EOL;
echo var_dump($this->connects_storage).PHP_EOL;
if (count($this->connects_storage) > 0) {
foreach ($this->connects_storage as $client) {
$client->sendString($message);
}
} else echo "There are empty storage";
}
答案 0 :(得分:-1)
$this->server->on("connect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Connected " . $user->getIp()));
array_push($this->connects_storage,$user);
});
$this->server->on("disconnect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Disconnected " . $user->getIp()));
});
$this->server->on("message", function (WebSocketTransportInterface $s_user, WebSocketMessageInterface $message) {
$s_user->sendString($message);
});
匿名函数/闭包无法序列化。您需要找出一种以不同方式存储它们的方法。
编辑:我花了一些时间来测试这段代码,(原来你不能用最新的php使用pthreads)。无论如何,我通过执行以下操作来解决您的问题:
将上面的代码替换为:
$this->server->on("connect", new Jeremeamia\SuperClosure\SerializableClosure(function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Connected " . $user->getIp()));
array_push($this->connects_storage,$user);
}));
$this->server->on("disconnect", new Jeremeamia\SuperClosure\SerializableClosure(function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Disconnected " . $user->getIp()));
}));
$this->server->on("message", new Jeremeamia\SuperClosure\SerializableClosure(function (WebSocketTransportInterface $s_user, WebSocketMessageInterface $message) {
$s_user->sendString($message);
}));
完成后,您需要包含正确的library,并且可能包含正确的文件(我总是无法让作曲家正确地自动加载内容)
答案 1 :(得分:-1)
您的WssService
对象不可序列化。为此,请制作$URL
和$port
成员变量,将初始化移至init()
方法,并实施__sleep()
和__wakeup()
方法:
class WssService
{
protected $URI, $port;
public $connects_storage = array();
private $server = null;
private $logger = null;
private $writer = null;
public $loop = null;
public function __construct($URI, $port)
{
$this->URI = $URI;
$this->port = $port;
$this->init();
}
protected function init() {
$this->connected_users = array();
$this->loop = \React\EventLoop\Factory::create();
$this->Logger = new \Zend\Log\Logger();
$this->writer = new Zend\Log\Writer\Stream("php://output");
$this->Logger->addWriter($this->writer);
$this->server = new WebSocketServer("tcp://" . $this->URI . ":" . $this->port, $this->loop, $this->Logger);
$this->server->on("connect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Connected " . $user->getIp()));
array_push($this->connects_storage,$user);
});
$this->server->on("disconnect", function (WebSocketTransportInterface $user) {
$this->Logger->notice((" Disconnected " . $user->getIp()));
});
$this->server->on("message", function (WebSocketTransportInterface $s_user, WebSocketMessageInterface $message) {
$s_user->sendString($message);
});
}
public function StartServer(){
$this->server->bind();
$this->loop->run();
}
public function SendForAll($message){
foreach($this->connects_storage as $client){
$client->sendString($message)
}
}
public function __sleep() {
return array('URI', 'port');
}
public function __wakeup() {
$this->init();
}
}
__sleep()
告诉序列化程序仅序列化$URI
和$port
个变量,这就是在反序列化过程中调用init()
中__wakeup()
所需的全部内容。