加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP线程SimpleXMLElement

发布时间:2020-12-13 17:46:29 所属栏目:PHP教程 来源:网络整理
导读:我一直在搜索这个问题而且我遇到了很多问题,但我不认为这是实际代码的问题. 基本上这个代码在两个独立的线程中启动套接字服务器(登录和游戏),我基本上从非线程版本转换了这个代码,但我一直无法让这个工作用于线程. include "socket.php";include "dep.php";c
我一直在搜索这个问题而且我遇到了很多问题,但我不认为这是实际代码的问题.
基本上这个代码在两个独立的线程中启动套接字服务器(登录和游戏),我基本上从非线程版本转换了这个代码,但我一直无法让这个工作用于线程.

include "socket.php";
include "dep.php";

class Server extends Thread {
    public $server;
    public $config;
    public function __construct($type){
        //$this->config = (string)$type;
        $this->run2($type);
        $this->run();
    }
    public function run(){
        while(true){
            $this->server->loop();
        }
    }
    public function run2($config){
        $this->server = new sokserv($config);
        $this->server->init();
        //while(true){
        //  $this->server->loop();
        //}
    }
}
$login = new Server('Config/config.xml');
$game = new Server("Config/config2.xml");
The error received is 
Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'SimpleXMLElement' is not allowed' in C:Users=DesktopTestStart.php:19
Stack trace:
#0 C:Users=DesktopTestStart.php(19): Server->run2()
#1 C:Users=DesktopTestStart.php(10): Server->run2('Config/config.x...')
#2 C:Users=DesktopTestStart.php(26): Server->__construct('Config/config.x...')
#3 {main}
  thrown in C:Users=DesktopTestStart.php on line 19

但是,恢复到旧代码工作正常.
sokserv的第一位(我删除了一些公共变量,因为它们包含个人信息)

class sokserv
{
    public $ip;
    public $port;
    public $users = array();
    public $config;
    public $mysql;
    private $socket;
    public function __construct($config = "Config/config.xml")
    {
        $this->readConfig($config);
    }
    public function readConfig($file)
    {
        if (!file_exists($file))
            die("Could not find config");
        $this->config = simplexml_load_file($file);
    }

如果你想要这是xml:

<server>
    <port>6112</port>
    <ip>0</ip>
    <mysql>
        <host>127.0.0.1</host>
        <username>root</username>
        <dbname></dbname> 
        <password></password>
        <table></table>
    </mysql>
</server>

解决方法

Zend内存管理器在TSRM的帮助下,专门用于禁止上下文共享数据;没有上下文可以在另一个线程中分配或释放任何东这被称为无共享架构,它完全符合它在锡上所说的内容. pthreads的工作是以安全,理智的方式突破这一障碍.

显然,与PHP捆绑在一起的扩展都没有意识到pthreads,我们也不想它们,因为它们会变得非常复杂.当谈到其他扩展提供的对象时,pthreads假设最安全的事情是序列化对象以进行存储.有些物体禁止这种情况发生,SimpleXML后代就是这样一组物体.

从pthreads下降的字符串,浮点数,整数和对象不是序列化的.从pthreads下降的对象hi-jack the serialization API,存储对象的物理地址,通过直接访问表示userland中对象的线程安全结构来避免序列化.

正确的解决方案是将您希望共享的数据包装在pthreads的后代对象中:

<?php
class Config extends Stackable {
    /**
    * Constructs thread safe,sharable configuration from complex XML
    * @param mixed $xml         SimpleXMLElement or location of XML file
    * @param array &$objects    reference store
    */
    public function __construct($xml,&$objects) {
        if ($xml instanceof SimpleXMLElement) {
            foreach ($xml as $key => $value)
                $this[$key] = (string) $value;
        } else {
            foreach (simplexml_load_string(
                        $xml) as $key => $value) {
                if ($value->children()) {
                    $this[$key] = new Config($value,$objects);
                } else $this[$key] = (string) $value;
            }
        }

        /* maintain object references */
        $objects[] = $this;
    }

    public function run() {}
}

class Test extends Thread {
    protected $config;

    /**
    * Constructs thread using pre-constructed thread safe,shared configuration object
    * @param Config $config
    */
    public function __construct(Config $config) {
        $this->config = $config;
    }

    public function run() {
        /* iterate over configuration */
        printf("%d settings:n",count($this->config));
        foreach ($this->config as $key => $data) {
            if (count($data) > 1) {
                printf( 
                    "t%s,%d settings:n",$key,count($data));
                foreach ($data as $name => $value) {
                    printf("tt%s = %sn",$name,$value);
                }
            } else printf("t%s = %sn",$data);
        }
        printf("n");

        printf(
            "Host: %s:%dn",$this->config->ip,$this->config->port);

        printf(
            "MySQL: %s@%s?database=%s&password=%s&table=%sn",$this->config->mysql->username,$this->config->mysql->host,$this->config->mysql->dbname,$this->config->mysql->password,$this->config->mysql->table);
    }
}

/* Example XML */
$xml = <<<XML
<server>
    <port>6112</port>
    <ip>some.ip</ip>
    <mysql>
        <host>127.0.0.1</host>
        <username>root</username>
        <dbname>somedb</dbname> 
        <password>somepass</password>
        <table>sometable</table>
    </mysql>
</server>
XML;

/* Object reference storage */
$objects = [];
$config = new Config($xml,$objects);

$thread = new Test($config);
$thread->start();

$thread->join();
?>

将输出以下内容:

3 settings:
        port = 6112
        ip = some.ip
        mysql,5 settings:
                host = 127.0.0.1
                username = root
                dbname = somedb
                password = somepass
                table = sometable

Host: some.ip:6112
MySQL: root@127.0.0.1?database=somedb&password=somepass&table=sometable

提供的示例使用您在问题中提供的[格式] XML,它采用该XML并创建它的线程安全表示,永远不会被序列化.

Config构造函数中的逻辑完全取决于您使用的XML的格式.

您可以将该Config对象传递给任意数量的线程,所有这些线程都可以读/写属性,并执行它的方法.

您打算共享的所有数据都应该以这种方式进行管理,您想要从中获取的不是您应该解决异常并尝试存储串行数据,而是应该为您的数据创建合适的容器实际上支持,正确,多线程.

进一步阅读:https://gist.github.com/krakjoe/6437782

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读