NotionCommotion Posted December 30, 2016 Share Posted December 30, 2016 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(); Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/ Share on other sites More sharing options...
kicken Posted December 30, 2016 Share Posted December 30, 2016 If both of those HTTP servers do the same thing there's no need to create two, just have one that listens on all addresses (unless you have a reason to limit the IPs). $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 print_r($query,1) . PHP_EOL; $response->end(print_r($query,1)); }); $http_socket1->listen('1337', '0.0.0.0'); If they do different things then I'd use different port numbers. While there's nothing to technically stop you from using the same port but different IP's it will be confusing and likely lead to trouble down the road. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540904 Share on other sites More sharing options...
NotionCommotion Posted December 30, 2016 Author Share Posted December 30, 2016 Different things. I will use separate port. Thanks! Did the part abou getting content from one instance to another make any sense? Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540905 Share on other sites More sharing options...
kicken Posted December 30, 2016 Share Posted December 30, 2016 Did the part abou getting content from one instance to another make any sense? Not really, which is why I was unsure if the two servers did the same thing or not. My understanding of what you wrote is you have Apache on port 80 and your custom server on port 1337. Scripts running via apache need to connect to your server to pass it some data. You also have some other external client scripts that need to connect to the server and send/receive data. It sounds like somewhere where a single server socket (on say 192.168.1.200:1337) would work, but two in order to easily distinguish between your apache clients and custom clients would also work fine. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540906 Share on other sites More sharing options...
NotionCommotion Posted December 31, 2016 Author Share Posted December 31, 2016 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 Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540911 Share on other sites More sharing options...
requinix Posted December 31, 2016 Share Posted December 31, 2016 I think the question here is whether "machine client" and "server" have to be separate; both running on the same server would greatly simplify the architecture. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540912 Share on other sites More sharing options...
NotionCommotion Posted December 31, 2016 Author Share Posted December 31, 2016 I think the question here is whether "machine client" and "server" have to be separate; both running on the same server would greatly simplify the architecture. Yes, it would greatly simplify the architecture, however, the are separate remote machines. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540913 Share on other sites More sharing options...
kicken Posted December 31, 2016 Share Posted December 31, 2016 I feel like your two machine client processed should be able to be combined as well as your two separate http servers which handle them. That would simplify things. Perhaps there is some reason for them being separate but from what I can recall of previous threads I don't see it. I'd think a setup something more like this could work. Your application server consists of two services. - Apache: Handles your normal web traffic and browsers. Scripts run here can use cURL to communicate with the PHP Server - PHP Server: Handles your remote client communications Your remote clients consist of a single service: - PHP Client: Handles your bi-directional communication needs. Has a periodic timer that does whatever your 1-minute cron task does. HTTP May not work for your bi-directional needs however, at least not using any pre-written library. The problem is you'd need to alternate which side is the server vs the client based on which side needs to initiate communication. To send data to the application server you'd have: HTTP Client(Remote client) ---> HTTP Server(Application server) where as to send data to the remote client you'd have HTTP Server(Remote client) <--- HTTP Client(Application server). You could stick with the two socket interface with say port 1337 being Remote Client ---> Application Server and 1338 being Remote Client <--- Application Server The JSON documents idea from the other thread would work fine with a single socket. You could just do something simple like each line is a json document and examine some field in that json to determine what to do. I'll code up a small example later. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540918 Share on other sites More sharing options...
NotionCommotion Posted December 31, 2016 Author Share Posted December 31, 2016 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 Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540920 Share on other sites More sharing options...
Solution kicken Posted January 1, 2017 Solution Share Posted January 1, 2017 I'll code up a small example later. Here's that example. To try and simulate your bi-direction traffic plus having a timed job I coded up a little Red-light/Green-light system. The server accepts clients and sends them random red or green light messages. When a client sees a green-light it fakes moving and stops when it gets a red-light. Periodically it also sends the server how far it's moved and it's name. The server periodically lists the players and their distance. There is pretty much no error handling (such as for disconnects) in the code, I'll leave that as an exercise to the reader. JSONStream.php - Sends and receives json documents via a socket stream. <?php namespace Kicken\RLGL; use Evenement\EventEmitterInterface; use Evenement\EventEmitterTrait; use React\Stream\DuplexStreamInterface; class JSONStream implements EventEmitterInterface { use EventEmitterTrait; private $socket; private $buffer; public function __construct(DuplexStreamInterface $socket){ $this->socket = $socket; $this->buffer = ''; $this->socket->on('data', function($data){ $this->buffer .= $data; $this->parseBuffer(); }); } public function send($structure){ $json = json_encode($structure); $this->socket->write($json."\r\n"); } private function parseBuffer(){ $eol = strpos($this->buffer, "\r\n"); while ($eol !== false){ $json = substr($this->buffer, 0, $eol); $this->buffer = substr($this->buffer, $eol + 2); $data = json_decode($json, true); if (json_last_error() == JSON_ERROR_NONE){ $this->emit('data', [$data]); } $eol = strpos($this->buffer, "\r\n"); } } } server.php - Short script to act as the server. Listens on port 1337 for connections and listens for info messages from each client. Sends light messages periodically. <?php require 'vendor/autoload.php'; require 'JSONStream.php'; $port = isset($argv[1])?$argv[1]:1337; $clientList = new SplObjectStorage(); $loop = new \React\EventLoop\StreamSelectLoop(); $socket = new React\Socket\Server($loop); $socket->on('connection', function (\React\Socket\ConnectionInterface $client) use (&$clientList){ $client = new \Kicken\RLGL\JSONStream($client); $clientList->attach($client, []); $client->on('data', function($data) use (&$clientList, $client){ if ($data['message'] == 'info'){ $clientList[$client] = $data['info']; } }); echo "New connection accepted.\r\n"; }); $loop->addPeriodicTimer(5, function () use ($clientList){ $color = mt_rand(1,2) == 1?'red':'green'; echo "Sending {$color} light.\r\n"; /** @var \Kicken\RLGL\JSONStream $client */ foreach ($clientList as $client){ $client->send([ 'message' => 'light' , 'color' => $color ]); } }); $loop->addPeriodicTimer(60, function() use ($clientList){ echo "Current results:\r\n"; foreach ($clientList as $client){ $info = $clientList[$client]; if (!empty($info)){ echo "{$info['name']} has travelled {$info['distance']} feet.\r\n"; } } }); $socket->listen($port, '0.0.0.0'); $loop->run(); client.php - Connects to the server and listens for light messages. Periodically tells the server how far it has travelled. <?php require 'vendor/autoload.php'; require 'JSONStream.php'; $server = isset($argv[1])?$argv[1]:'127.0.0.1'; $port = isset($argv[2])?$argv[2]:1337; /** @var \Kicken\RLGL\JSONStream $client */ $client = null; $clientInfo = [ 'name' => getRandomName() , 'speed' => getRandomSpeed() , 'traveled' => 0 , 'moving' => false , 'movingStartTime' => null ]; $loop = new \React\EventLoop\StreamSelectLoop(); $socket = new \React\SocketClient\TcpConnector($loop); $socket->create($server, $port)->then(function ($stream) use (&$client, &$clientInfo){ $client = new \Kicken\RLGL\JSONStream($stream); sendClientInfo(); $client->on('data', function ($data) use (&$clientInfo){ if ($data['message'] == 'light'){ if ($data['color'] == 'green' && !$clientInfo['moving']){ $clientInfo['moving'] = true; $clientInfo['movingStartTime'] = time(); echo "Received green light!\r\n"; } else if ($data['color'] == 'red' && $clientInfo['moving']){ $movingTime = time() - $clientInfo['movingStartTime']; $distance = $movingTime * $clientInfo['speed']; $clientInfo['traveled'] += $distance; $clientInfo['moving'] = false; $clientInfo['movingStartTime'] = null; echo "Received Red light! Total distance = {$distance} feet.\r\n"; } } }); }); $loop->addPeriodicTimer(15, 'sendClientInfo'); $loop->run(); function sendClientInfo(){ global $client, $clientInfo; $infoToSend = [ 'name' => $clientInfo['name'] , 'distance' => $clientInfo['traveled'] ]; echo "Updating server with data.\r\n"; $client->send(['message' => 'info', 'info' => $infoToSend]); } function getRandomName(){ static $names = ['Edmundo', 'Roxane', 'Evelynn', 'Isaias', 'Buena', 'Evan', 'Katharina', 'Darnell', 'Sharyl', 'Malka', 'Sharla', 'Delena', 'Leah', 'Marnie', 'Tammi', 'Joanna', 'Marva', 'Karyn', 'Kristal', 'Jayson']; shuffle($names); return $names[0]; } function getRandomSpeed(){ return mt_rand(1, 100) / 100; } Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540924 Share on other sites More sharing options...
NotionCommotion Posted January 1, 2017 Author Share Posted January 1, 2017 (edited) 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]$ Edited January 1, 2017 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540927 Share on other sites More sharing options...
NotionCommotion Posted January 1, 2017 Author Share Posted January 1, 2017 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){}); Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540937 Share on other sites More sharing options...
kicken Posted January 2, 2017 Share Posted January 2, 2017 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. react/react is older and not really intended to be used anymore, instead you're supposed to just include the individual libraries as needed. My composer requirements for the example were: "require": { "react/socket": "^0.4.4", "react/stream": "^0.4.5", "react/event-loop": "^0.4.2", "react/socket-client": "^0.5.3" } Is there any difference between these two lines? Using the factory is probably better in general. The factory will look for the best event loop implementation your setup can support. Also, why is $client defined outside of it? So I can also use it in the sendClientInfo function later on. In reality it'd be better to create some classes for the client and server so that state like the connection and client information can be tracked as member variables. Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540939 Share on other sites More sharing options...
NotionCommotion Posted January 3, 2017 Author Share Posted January 3, 2017 react/react is older and not really intended to be used anymore, instead you're supposed to just include the individual libraries as needed. My composer requirements for the example were: 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; } } Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1540990 Share on other sites More sharing options...
kicken Posted January 3, 2017 Share Posted January 3, 2017 Thanks. Just curious, how do you know this? I haven't found too much documentation. Their notice about it being split into components and the fact that the main repository has not had any significant updates in a long time provides a strong hint. If you dig into the the issues area you'd also find an issue named Mark react/react as abondoned in order to redirect people to new components. 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?Wrap your connection code into a simple connect() method. You can then monitor the socket for a disconnect and simple call the connect() method again to reconnect if desired. There shouldn't be any need to clean up any of the socket objects or what not. PHP will take care of the memory management and the socket will already have been closed. To handle an error connecting to the server you can use the otherwise method on the promise. You'll also likely want to use a TimeoutConnector so you can control timeout. Also note that my JSONStream doesn't forward events, it only emits it's own data event. To monitor the close event you'd have to either modify the class to forward it or watch the underlying stream object. class Client { //... public function start(){ $this->loop = Factory::create(); $this->connect(); $this->loop->run(); } private function connect(){ $socket = new TimeoutConnector(new TcpConnector($this->loop), 10, $this->loop); $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); }); $stream->on('close', function(){ $this->connection = null; //Determine whether or not to reconnect //call $this->connect(); if you want to reconnect }); })->otherwise(function($reason){ //Handle connection error //call $this->connect() to try again }); } } 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? You'd just have to implement your own buffering on top of it's buffering. I probably wouldn't really bother though since their buffer limit is implemented more as a suggestion rather than a hard limit. Their buffer class will accept whatever data you throw at it but begins returning false after 64k as hint that maybe you should wait a bit before sending more. If you want to protected against them possibly changing their code to make it a hard limit then you'd just change send to append data to a variable and another variable to track whether the socket buffer is full or not. Add a listener for the drain event and if you have any data in your buffer try to write it and update the buffer full variable. You can look at their buffer class as an example, you'd be doing basically the same thing but without a limit. 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? You could create some kind of adjustable timer class that handles re-registering a timer and use that from within your application class. For example class AdjustableTimer { private $loop; private $interval; private $callback; private $timer; public function __construct(LoopInterface $loop, $interval, callable $callback){ $this->loop = $loop; $this->interval = $interval; $this->callback = $callback; $this->start(); } public function setInterval($interval){ $this->interval = $interval; $this->start(); } public function stop(){ $this->loop->cancelTimer($this->timer); $this->timer = null; } public function start(){ if ($this->timer){ $this->stop(); } $this->timer = $this->loop->addPeriodicTimer($this->interval, $this->callback); } } Add a method to your client that will construct a variable timer and return it. class Client { //... public function createAdjustableTimer($interval, $callback){ return new AdjustableTimer($this->loop, $interval, $callback); } } 1 Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1541005 Share on other sites More sharing options...
NotionCommotion Posted January 4, 2017 Author Share Posted January 4, 2017 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(); }); ### Connection timeouts The `TimeoutConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to add timeout handling to any existing connector instance. It does so by decorating any given [`ConnectorInterface`](#connectorinterface) instance and starting a timer that will automatically reject and abort any underlying connection attempt if it takes too long. ```php $timeoutConnector = new React\SocketClient\TimeoutConnector($connector, 3.0, $loop); $timeoutConnector->create('google.com', 80)->then(function (React\Stream\Stream $stream) { // connection succeeded within 3.0 seconds }); In regards to AdjustableTimer, I would still need to pass Client to ClientApp, right? Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1541035 Share on other sites More sharing options...
kicken Posted January 4, 2017 Share Posted January 4, 2017 If I ran the following without a connection, it would echo "otherwise" continuously. That is to be expected, right?Yep. In regards to AdjustableTimer, I would still need to pass Client to ClientApp, right?Yep, you'd still have to be able to call the createAdjustableTimer method on the client. $this->timer = $this->client->createAdjustableTimer(60, function(){ echo "Cron"; }); //... $this->timer->setInterval(10); Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1541051 Share on other sites More sharing options...
NotionCommotion Posted January 4, 2017 Author Share Posted January 4, 2017 Perfect. Thanks again. I really owe you! Now on to the server.... Quote Link to comment https://forums.phpfreaks.com/topic/302840-http-server-with-two-hosts-and-same-port/#findComment-1541052 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.