Jump to content

NotionCommotion

Members
  • Posts

    2,446
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by NotionCommotion

  1. Sorry, just realized that I did not enclose all the script in script tags... <?php class Foo { private $storage; private $map; public function __construct() { $this->storage = new SplObjectStorage(); $this->map=[]; } public function add($obj) { $this->storage->attach($obj, []); } public function assign1($obj,$id) { $this->storage[$obj] = $id; } public function findByID1($id) { $this->storage->rewind(); while($this->storage->valid()) { if($id == $this->storage->getInfo()) { return $this->storage->current(); } $this->storage->next(); } return false; } public function assign2($obj,$id) { $this->map[$id]=spl_object_hash($obj); } public function findByID2($id) { $hash=$this->map[$id]; //return getObjectBasedOnHash($hash); //How is this accomplished? } } $obj=(object)['foo' => 'bar']; $foo=new Foo(); $foo->add($obj); //Now this object's id is known $id=11111; $id=123321; //Option 1 $foo->assign1($obj,$id); $obj1=$foo->findByID1($id); //Option 2 $foo->assign2($obj,$id); $obj2=$foo->findByID2($id);
  2. How can I retrieve an object stored in SplObjectStorage based on a unique key? Is it possible to do so the way I am attempting to show in my 2 example? <?php class Foo { private $storage; private $map; public function __construct() { $storage = new SplObjectStorage(); $map=[]; } public function add(object $obj) { $this->storage->attach($obj, []); } public function assign1($obj,$id) { $this->storage[$obj] = $id; } public function findByID1($id) { $this->storage->rewind(); while($this->storage->valid()) { if($id == $this->storage->getInfo()) { return $this->storage->current(); } $this->storage->next(); } return false; } public function assign2($obj,$id) { $this->map[$id]=spl_object_hash($obj); } public function findByID2($id) { $hash=$this->map[$id]; return getObjectBasedOnHash($hash); } } $obj=(object)['foo' => 'bar']; $foo=new Foo(); $foo->add($obj); //Now this object's id is known $id=11111; $foo->assign1($obj,$id); $obj1=$foo->findByID1($id); $foo->assign2($obj,$id); $obj2=$foo->findByID2($id);
  3. Is this something that only you will do from your own computer, or other users will do from their potentially different browser types? If the former, I would consider a browser solution. Use JavaScript (or derivatives of such as jQuery) to understand the DOM, and just a form or Ajax to send it to your PHP/MySql server.
  4. Perfect. Thanks again. I really owe you! Now on to the server....
  5. Thanks again. So, TimeoutConnector just closes a connection if not made within a given time frame. If I ran the following without a connection, it would echo "otherwise" continuously. That is to be expected, right? $socket = new TimeoutConnector(new TcpConnector($this->loop), 10, $this->loop); $socket->create($this->app->config->host, $this->app->config->port)->then(function($stream){ // connection succeeded within 10.0 seconds })->otherwise(function($reason){ // Over 10 seconds or reasons do to TcpConnector()->create() echo "otherwise" . PHP_EOL; $this->connect(); }); In regards to AdjustableTimer, I would still need to pass Client to ClientApp, right?
  6. Thanks. Just curious, how do you know this? I haven't found too much documentation. I am focusing on the client (not yet tested) part at first, and have a couple of questions: Does it make sense to use a class for client as I have done so? If the server is not started when the client is started, send() will result in an error. Also, if the server had first been started, but then stopped, I don't think it will reconnect automatically. My plan is to utilize another loop to check the connection, and if not connected, reconnect. Am I doing this correctly? Also,upon connection close, do I need to take additional actions? How can I modify send() so that the buffer will never be exceeded? I expect I will need drain. Can it be done without becoming blocking? The application (code not posted) needs to be able to change the cron addPeriodicTimer period and also needs to be able to send data. To do so, I pass client to the app within clients constructor. This doesn't seem quite right, but I don't know what else to do. Thoughts? Thanks! <?php require '../../../vendor/autoload.php'; use MyServer\Client; use MyServer\ClientApp; $logger = new \Monolog\Logger('my_logger'); $logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__."/logs/client.log")); $logger->addInfo('Server started'); $db = new \PDO("sqlite:".__DIR__."/db/datalogger.db"); $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $db->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ); $client=new Client(new ClientApp($db, $logger)); $client->start(); <?php namespace MyServer; use React\EventLoop\Factory; use React\SocketClient\TcpConnector; class Client { private $app, //The main application $host, $port, //The IP and port of the remote server $loop, //The main loop $cron, //The main work timer. Can be changed by $app $connection=false; //The sockets connection public function __construct($app, $host, $port) { $this->app = $app; /* The main application needs to be able to send data and change the main addPeriodicTimer period. I Don't really like how I am doing this, but don't know how else, and ideally I would just give access to these two methods. */ $this->app->client=$this; } public function start() { $this->loop = Factory::create(); $socket = new TcpConnector($this->loop); $this->loop->addPeriodicTimer(1, function() { if(!$this->connection) { $socket->create($this->app->config->host, $this->app->config->port)->then(function ($stream) { $this->connection = new \Kicken\RLGL\JSONStream($stream); $this->connection->send($this->app->identifyCommand()); //Sends clients identity to server $this->connection->on('data', function ($data) { $this->app->process($data); }); $this->connection->on('close', function() { $this->connection = false; //Do I need to destroy the socket, etc? }); }); } }); $this->cron=$this->loop->addPeriodicTimer($this->app->getCronTimer(), function(){ $this->client->doCron(); }); $this->loop->run(); } public function changeTimer($period) { $this->loop->cancelTimer($this->cron); $this->cron = $this->loop->addPeriodicTimer($period, function(){ $this->client->cron(); }); } public function send($data) { if($this->connection) { //How is drain handled to ensure that $data doesn't exceed buffer? $this->connection->send($data); } return $this->connection; } }
  7. I don't think it just about "PDO" exceptions, but exceptions in general. If you need/want to do something exceptional, catch them and do so. Otherwise, ...
  8. Using composer, I was able to remove react, then add socket-client:^0.5.3. Can't now add "react/react": "^0.4.2" back. Don't know if it will cause any issues. Thank you for the sample script. It really helps. A couple of questions: Is there any difference between these two lines? $loop = new \React\EventLoop\StreamSelectLoop(); $loop = React\EventLoop\Factory::create(); Could you shed some light on this line. Also, why is $client defined outside of it? $socket->create($server, $port)->then(function ($stream) use (&$client, &$clientInfo){});
  9. Maybe more, but your array element shouldn't be :e but just e. $sql->execute(array('e' => $ADDRESS));
  10. Thank you Kicken! I haven't gone through it in detail yet, however, I do like the way you are parsing the JSON more than my approach described by https://forums.phpfreaks.com/topic/302843-parsing-newline-delimited-json/. One initial snag. Class React\SocketClient\TcpConnector is not found. I have the socket-client directory, however, don't have the TcpConnector.php file in it. Looking at https://github.com/reactphp/socket-client/tree/master/src, however, I see the file. Do I also need to add "react/socket-client" to the composer file? My composer setup is shown below. [Michael@devserver react]$ ls -l total 44 drwxrwxr-x. 4 Michael Michael 4096 Nov 21 05:26 cache drwxrwxr-x. 4 Michael Michael 4096 Nov 21 05:26 child-process drwxrwxr-x. 4 Michael Michael 4096 Nov 21 05:26 dns drwxrwxr-x. 4 Michael Michael 4096 Nov 21 05:26 event-loop drwxrwxr-x. 5 Michael Michael 4096 Nov 21 05:26 http drwxrwxr-x. 5 Michael Michael 4096 Dec 28 06:09 http-client drwxrwxr-x. 4 Michael Michael 4096 Dec 28 06:08 promise drwxrwxr-x. 7 Michael Michael 4096 Nov 21 05:26 react drwxrwxr-x. 5 Michael Michael 4096 Dec 28 06:08 socket drwxrwxr-x. 4 Michael Michael 4096 Dec 28 06:09 socket-client drwxrwxr-x. 5 Michael Michael 4096 Nov 21 05:26 stream [Michael@devserver react]$ ls socket-client -l total 28 -rw-rw-r--. 1 Michael Michael 1829 Dec 6 02:54 CHANGELOG.md -rw-rw-r--. 1 Michael Michael 545 Dec 6 02:54 composer.json -rw-rw-r--. 1 Michael Michael 1069 Dec 6 02:54 LICENSE -rw-rw-r--. 1 Michael Michael 666 Dec 6 02:54 phpunit.xml.dist -rw-rw-r--. 1 Michael Michael 3171 Dec 6 02:54 README.md drwxrwxr-x. 2 Michael Michael 4096 Dec 6 02:54 src drwxrwxr-x. 2 Michael Michael 4096 Dec 6 02:54 tests [Michael@devserver react]$ ls socket-client/src -l total 28 -rw-rw-r--. 1 Michael Michael 94 Dec 6 02:54 ConnectionException.php -rw-rw-r--. 1 Michael Michael 113 Dec 6 02:54 ConnectorInterface.php -rw-rw-r--. 1 Michael Michael 2811 Dec 6 02:54 Connector.php -rw-rw-r--. 1 Michael Michael 1529 Dec 6 02:54 SecureConnector.php -rw-rw-r--. 1 Michael Michael 2185 Dec 6 02:54 SecureStream.php -rw-rw-r--. 1 Michael Michael 3605 Dec 6 02:54 StreamEncryption.php -rw-rw-r--. 1 Michael Michael 875 Dec 6 02:54 UnixConnector.php [Michael@devserver react]$ { "require": { "react/react": "^0.4.2", "vlucas/phpdotenv": "^2.4", "monolog/monolog": "^1.19", "slim/slim": "^3.4", "slim/twig-view": "^2.1" }, "autoload": { "psr-4": { "MyServer\\": "src/" }, "files": [ "src/Support/helpers.php" ] } } [Michael@devserver datalogger]$ composer require react/socket-client:^0.5.3 ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - react/react v0.4.2 requires react/socket-client 0.4.* -> satisfiable by react/socket-client[0.4.x-dev, v0.4.0, v0.4.1, v0.4.2, v0.4.3, v0.4.4, v0.4.5, v0.4.6] but these conflict with your requirements or minimum-stability. - react/react v0.4.2 requires react/socket-client 0.4.* -> satisfiable by react/socket-client[0.4.x-dev, v0.4.0, v0.4.1, v0.4.2, v0.4.3, v0.4.4, v0.4.5, v0.4.6] but these conflict with your requirements or minimum-stability. - react/react v0.4.2 requires react/socket-client 0.4.* -> satisfiable by react/socket-client[0.4.x-dev, v0.4.0, v0.4.1, v0.4.2, v0.4.3, v0.4.4, v0.4.5, v0.4.6] but these conflict with your requirements or minimum-stability. - Installation request for react/react ^0.4.2 -> satisfiable by react/react[v0.4.2]. Installation failed, reverting ./composer.json to its original content. [Michael@devserver datalogger]$
  11. Thanks Kicken, It does seem like I can and should combine the clients and servers. The only reason I was thinking of not doing so is to use HTTP when possible and otherwise using some low level sockets. Let me more review your commends and think it over. Thanks
  12. Am I doing this correctly? Thanks <?php function parse($s) { static $buffer; $jsons=[]; $arr=[]; $parts=explode('\n',$s); $count=count($parts); if($count===1) { $buffer.=$parts[0]; } elseif($count===2) { if($start=$buffer.$parts[0]) $jsons[]=$start; $buffer=$parts[1]; } else { if($start=$buffer.$parts[0]) $jsons[]=$start; if($count>3) { $jsons=array_merge($jsons,array_slice($parts,1,$count-2)); } $buffer=$parts[$count-1]; } foreach($jsons as $json) { $arr[]=json_decode($json); } return $arr; } var_dump(parse('{"a":123,"b":[1,2')); var_dump(parse('')); var_dump(parse(',3]}\n{"a":321,"b":[3,2,1]}\n{"a":111,"b":[1,1,1]}\n{"a":333,"b":[3,3,3]}\n{"a":123,"b":[1,2,3]}\n{"a"')); var_dump(parse(':321,"b":[3,2,1]}\n{"a":111,"b":[1,1,1]}\n{"a":333,"b":[3,3,3]}\n')); var_dump(parse('{"a":333,"b":[3,3,3]}\n')); array(0) { } array(0) { } array(5) { [0]=> object(stdClass)#1 (2) { ["a"]=> int(123) ["b"]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } } [1]=> object(stdClass)#2 (2) { ["a"]=> int(321) ["b"]=> array(3) { [0]=> int(3) [1]=> int(2) [2]=> int(1) } } [2]=> object(stdClass)#3 (2) { ["a"]=> int(111) ["b"]=> array(3) { [0]=> int(1) [1]=> int(1) [2]=> int(1) } } [3]=> object(stdClass)#4 (2) { ["a"]=> int(333) ["b"]=> array(3) { [0]=> int(3) [1]=> int(3) [2]=> int(3) } } [4]=> object(stdClass)#5 (2) { ["a"]=> int(123) ["b"]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } } } array(3) { [0]=> object(stdClass)#5 (2) { ["a"]=> int(321) ["b"]=> array(3) { [0]=> int(3) [1]=> int(2) [2]=> int(1) } } [1]=> object(stdClass)#4 (2) { ["a"]=> int(111) ["b"]=> array(3) { [0]=> int(1) [1]=> int(1) [2]=> int(1) } } [2]=> object(stdClass)#3 (2) { ["a"]=> int(333) ["b"]=> array(3) { [0]=> int(3) [1]=> int(3) [2]=> int(3) } } } array(1) { [0]=> object(stdClass)#3 (2) { ["a"]=> int(333) ["b"]=> array(3) { [0]=> int(3) [1]=> int(3) [2]=> int(3) } } }
  13. Yes, it would greatly simplify the architecture, however, the are separate remote machines.
  14. Hi Kicken, Does the following help? Web client needs to send data to machine client. It does so by sending data to web application which then cURLs it to a HTTP server which is tightly coupled to a socket server which is connected to the socket client. This seems a little excessive, but I don't know what would be better. Maybe a Redis queue? Also, the machine client needs to periodically send a lot of data to the server. Originally, I planned on just using the low-level sockets connection, but this post https://forums.phpfreaks.com/topic/302824-help-with-sockets-and-reactphp/ made me change my mind. Thanks
  15. Different things. I will use separate port. Thanks! Did the part abou getting content from one instance to another make any sense?
  16. Or let your normal error handler catch the uncaught exception. Or use a template engine such as http://twig.sensiolabs.org/. Most of mac_gyver's great comments were not specifically about PDO. Remember PDO is easy, and remember to have fun! Happy New Year to you and all others!
  17. Is there any problem creating two HTTP servers with the same port, but using localhost as one host and the server's static IP as the other? I've tested it and it seems to be okay. PS. Why I am doing this.... The server runs a socket server service which can be connected by one or more machines which have socket clients which allows bidirectional communication. An Apache HTTP server 192.168.1.200:80 running on the same server receives requests, and needs to forward data to the socket server and onward to the applicable socket client. To do so, I added a HTTP server 127.0.0.1:1337 to the script which implements the socket server and the scripts on 192.168.1.200:80 make a cURL request to localhost. (While this works, should I instead use a Redis queue, or some other means to do this???) The machines with the socket clients described above also need to send large amounts of data to the server. Originally, I was going to use the low level socket connection, but am changing to HTTP and will use cURL to have these devices make a HTTP request to 192.168.1.200:1337. <?php require 'vendor/autoload.php'; use React\EventLoop\Factory; use React\Http\Server as HttpServer; use React\Socket\Server as SocketServer; set_time_limit(0); $loop = Factory::create(); $http_socket1 = new SocketServer($loop); $http1 = new HttpServer($http_socket1); $http1->on('request', function ($request, $response) { $response->writeHead(200, array('Content-Type' => 'text/plain')); $query = $request->getQuery(); echo '127.0.0.1' . PHP_EOL; echo print_r($query,1) . PHP_EOL; $response->end(print_r($query,1)); }); $http_socket1->listen('1337', '127.0.0.1'); $http_socket2 = new SocketServer($loop); $http2 = new HttpServer($http_socket2); $http2->on('request', function ($request, $response) { $response->writeHead(200, array('Content-Type' => 'text/plain')); $query = $request->getQuery(); echo '192.168.1.200' . PHP_EOL; echo print_r($query,1) . PHP_EOL; $response->end(print_r($query,1)); }); $http_socket2->listen('1337', '192.168.1.200'); $loop->run();
  18. GET data seems pretty straight forward, but not so with POST data. It seems to work, however, that does not necessarily mean it is right. Am I doing it right? Thanks <?php require 'vendor/autoload.php'; use React\EventLoop\Factory; use React\Http\Server as HttpServer; use React\Socket\Server as SocketServer; set_time_limit(0); $port='1337'; //$host='0.0.0.0'; //$host='127.0.0.1'; $host='192.168.1.200'; //$host='192.168.1.201'; $loop = Factory::create(); $http_socket = new SocketServer($loop); $http = new HttpServer($http_socket); $http->on('request', function ($request, $response) { switch($request->getMethod()) { case 'GET': $response->writeHead(200, array('Content-Type' => 'text/plain')); $query = $request->getQuery(); echo print_r($query,1) . PHP_EOL; $response->end(print_r($query,1)); break; case 'POST': $requestBody = ''; $headers = $request->getHeaders(); $contentLength = (int)$headers['Content-Length']; $receivedData = 0; $request->on('data',function($data) use ($request, $response, &$requestBody, &$receivedData, $contentLength) { $requestBody.=$data; $receivedData+=strlen($data); if ($receivedData>=$contentLength) { parse_str($requestBody, $query); $response->writeHead(200, array('Content-Type' => 'text/plain')); echo print_r($query,1) . PHP_EOL; $response->end(print_r($query,1)); } }); break; } }); $http_socket->listen($port, $host); $loop->run();
  19. Ah ha! I was about to question kicken about his clairvoyance, but then saw your post. I noticed the httpd, but incorrectly thought it was some sort of reactphp http server that the script in question was attempting to create.
  20. I never said I ran such a script via Apache, but you guessed correct, and believe that was the cause! I occasionally do so for IDE debugging purposes only.
  21. Maybe a silly mistake, and had another script running? I didn't think so, but starting to think so.
  22. I am getting the following error. It is caused when I first bind a connection, then get some error halting the code, and then try the code again, but it is already bound. [Michael@devserver datalogger]$ sudo netstat -lnptu | grep 1337 tcp 0 0 192.168.1.200:1337 0.0.0.0:* LISTEN 3899/httpd [Michael@devserver datalogger]$ My solution has been to reboot the machine or kill -9 3899. Instead, can I if necessary first check if tcp://192.168.0.100:1337 is already bound, and then unbind it using PHP, and then proceed? I thought $socket->shutdown() might work, but nope. <?php require 'vendor/autoload.php'; use React\EventLoop\Factory; use React\Socket\Server as SocketServer; use React\Http\Server as HttpServer; $loop = Factory::create(); $socket = new SocketServer($loop); //$socket->shutdown(); //Close if currently open $socket->on('connection', function($conn) {/* ... */}); $socket->listen(1337,'192.168.0.100'); [Michael@devserver react]$ php xxx.php PHP Fatal error: Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://192.168.0.100:1337: Cannot assign requested address' in /var/www/react/vendor/react/socket/src/Server.php:29 Stack trace: #0 /var/www/react/xxx.php(13): React\Socket\Server->listen(1337, '192.168.0.100') #1 {main} thrown in /var/www/react/vendor/react/socket/src/Server.php on line 29 Fatal error: Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://192.168.0.100:1337: Cannot assign requested address' in /var/www/react/vendor/react/socket/src/Server.php:29 Stack trace: #0 /var/www/react/xxx.php(13): React\Socket\Server->listen(1337, '192.168.0.100') #1 {main} thrown in /var/www/react/vendor/react/socket/src/Server.php on line 29 [Michael@devserver react]$
  23. So, it is just cool?
  24. While you "could" post from one page to another, don't and use sessions. <?php // Page 1 session_start(); $_SESSION['message']=$message; <?php // Page 2 session_start(); echo($_SESSION['message']);
  25. I know I don't have to use this port, however, all the examples use this port, and wonder if they have any reasons to do so. A Google search of Port 1337 revealed nothing of interest.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.