$clients = array(); public function __construct( IThriftProcessor $processor, TServerSocket $serverTransport, TTransportFactory $transportFactory, TProtocolFactory $protocolFactory, ) { parent::__construct( $processor, $serverTransport, $transportFactory, $protocolFactory, ); } /** * Because our server is non-blocking, don't close this socket * until we need to. * * @return bool true if we should keep the client alive */ protected function handle(TBufferedTransport $client): bool { $trans = $this->transportFactory->getTransport($client); $prot = $this->protocolFactory->getProtocol($trans); $this->_clientBegin($prot); try { // First check the transport is readable to avoid // blocking on read if (!($trans instanceof TTransportStatus) || $trans->isReadable()) { $this->processor->process($prot, $prot); } } catch (Exception $x) { $md = $client->getMetaData(); if ($md['timed_out']) { // keep waiting for the client to send more requests } else if ($md['eof']) { invariant($trans instanceof TTransport, 'Need to make Hack happy'); $trans->close(); return false; } else { echo 'Handle caught transport exception: '.$x->getMessage()."\n"; } } return true; } protected function processExistingClients(): void { foreach ($this->clients as $i => $client) { if (!$this->handle($client)) { // remove the client from our list of open clients if // our handler reports that the client is no longer alive unset($this->clients[$i]); } } } /* * This method should be called repeately on idle to listen and * process an request. If there is no pending request, it will * return; */ public function serve(): void { $this->serverTransport->listen(); $this->process(); } public function process(): void { // 0 timeout is non-blocking $client = $this->serverTransport->accept(0); if ($client) { $this->clients[$this->clientIdx++] = $client; } $this->processExistingClients(); } }