2016-04-13 29 views
8

Sto utilizzando un pacchetto di composizione owlycode/streaming-bird per chiamare twitter stream API. L'API stream apre una presa tra la tua app e Twitter, per ricevere tweet con una parola chiave specificata. Nel mio caso la parola chiave è "ciao".Come controllare in PHP, se un socket è ancora connesso, se non ho il gestore di socket?

Ecco il pacchetto owlycode/streaming-uccello codice utilizzando:

<?PHP 
    $oauthToken = ''; 
    $oauthSecret = ''; 
    $consumerKey = ''; 
    $consumerSecret = ''; 

    $bird = new StreamingBird($consumerKey, $consumerSecret, $oauthToken, $oauthSecret); 

    $bird 
     ->createStreamReader(StreamReader::METHOD_FILTER) 
     ->setTrack(['hello']) // Fetch every tweet containing one of the following words 
     ->consume(function ($tweet) { // Now we provide a callback to execute on every received tweet. 
      echo '------------------------' . "\n"; 
      echo $tweet['text'] . "\n"; 
     }); 
    ?> 

mio problema è quando questa connessione è chiusa da un errore, non sono in grado di sapere che. Quindi non riesco più a riconnetterti con Twitter.

C'è qualcosa in PHP che cerca i socket aperti in base al loro nome di dominio?

Forse qualcosa di simile

check_if_socket_open('https://stream.twitter.com/1.1/statuses/firehose.json') 

?

Nota: non riesco a utilizzare socket_get_status, perché non ho la variabile socket.

+0

E [Sembra a me] (https://github.com/OwlyCode/StreamingBird/blob/master/src/StreamReader.php#L80) come se continuasse a ricollegare il socket in caso di perdita della connessione. – miken32

+0

Solo guardando la documentazione inline, sembra che @ miken32 sia corretto, penso che il problema sia il tempo necessario per rilevare una perdita di connessione ... per esempio: se il timeout è impostato su 1 minuto ... allora avrai perso 1 minuto del flusso – edhurtig

+0

Anche se si tratta di una soluzione sbagliata ... potrebbe valere la pena esaminare stream_set_timeout ($ stream, $ secondi) per altri motivi. http://php.net/manual/en/function.stream-set-timeout.php – edhurtig

risposta

1

Sembra che dopo tutto si possa usare socket_get_status se si fa una piccola aggiunta nel pacchetto stesso.

Queste due funzioni sono in classe streamreader, il gestore di socket è disponibile qui.

public function consume(callable $handler) 
{ 
    $this->running = true; 
    while ($this->running) { /// while $this->running is true socket will try to reconnect always. 
     $this->consumeOnce($handler); 
    } 
} 
    protected function consumeOnce(callable $handler) 
    { 
     $this->connection = $this->connect(); 
     $lastStreamActivity = time(); 
     $this->connection->read(function ($tweet) use (&$lastStreamActivity, $handler) { 
      $idle = (time() - $lastStreamActivity); 
      $this->monitor->stat('max_idle_time', $idle); 
      $this->monitor->stat('idle_time', $idle); 
      $this->monitor->stat('tweets', 1); 
      $lastStreamActivity = time(); 
      call_user_func($handler, $tweet, $this->monitor); 
     }); 
     $this->connection->close(); 
    } 

In classe di connessione avete il gestore presa disponibile in modo da poter afferrare lo stato presa quando si cerca di leggere i dati da presa. Qui di seguito è una funzione di lettura leggermente modificata

public function read(callable $callback, $timeout = 5) 
     { 
      $this->pool = [$this->connection]; 
    stream_set_timeout($this->connection, $timeout); 
    $info = stream_get_meta_data($this->connection); 
      while ($this->connection !== null && !feof($this->connection) && stream_select($this->pool, $fdw, $fde, $timeout) !== false && $info['timed_out']!==true) { 
       // @todo safeguard no tweets but connection OK. (reconnect) 
       $this->pool = [$this->connection]; 
       $chunkInfo = trim(fgets($this->connection)); 
       if (!$chunkInfo) { 
        continue; 
       } 
       $len = hexdec($chunkInfo) + 2; 
       $streamInput = ''; 
       while (!feof($this->connection)) { 
        $streamInput .= fread($this->connection, $len-strlen($streamInput)); 
        if (strlen($streamInput)>=$len) { 
         break; 
        } 
       } 
       $this->buffer .= substr($streamInput, 0, -2); 
       $data = json_decode($this->buffer, true); 
       if ($data) { 
        call_user_func($callback, $data); 
        $this->buffer = ''; 
       } 
      } 
     } 
4

Non v'è alcun modo per verificare lo stato presa, se hai accesso alla presa.

Se siete alla ricerca di una soluzione senza toccare il codice di StreamBird, allora si può fare una classe basata su \OwlyCode\StreamingBird, quindi implementare la sua connect metodo:

<?php 
class MyStreamReader extends \OwlyCode\StreamingBird 
{ 
    protected $stream; 

    protected function connect($timeout = 5, $attempts = 10) 
    { 
    return $this->stream = parent::connect($timeout, $attempts); 
    } 

    protected function isConnected() 
    { 
    return $this->stream && stream_get_meta_data($this->stream)['eof']; 
    } 
} 


class MyStreamingBird extends \OwlyCode\StreamingBird 
{ 
    public function createStreamReader($method) 
    { 
    $oauth = new \OwlyCode\StreamingBird\Oauth($this->consumerKey, 
     $this->consumerSecret, $this->oauthToken, $this->oauthSecret); 
    return new MyStreamReader(new \OwlyCode\StreamingBird\Connection(), $oauth, $method); 
    } 
} 


$bird = new MyStreamingBird($consumerKey, $consumerSecret, $oauthToken, $oauthSecret); 
$reader = $bird->createStreamReader(StreamReader::METHOD_FILTER); // ... 

$reader->isConnected(); 

Si può anche fare una classe basata su \OwlyCode\StreamingBird, che ha anche accesso allo stream. Tuttavia, dovrai tenere traccia di questi flussi, perché è un metodo di fabbrica.

1

Guardando il implementation of class StreamingBird, si vede si può facilmente creare l'istanza StreamReader da soli, con il pieno controllo del collegamento:

namespace \OwlyCode\StreamingBird; 
// Let's instantiate the Oauth signature handler 
$oauth = new Oauth($consumerKey, $consumerSecret, $oauthToken, $oauthSecret); 
// Let's create our own Connection object! 
$connection = new Connection(); 

// And here comes our Reader 
$reader = new StreamReader($connection, $oauth, StreamReader::METHOD_FILTER); 
$reader->setTrack(['hello']) 
     ->consume(function ($tweet) { 
      echo '------------------------' . "\n"; 
      echo $tweet['text'] . "\n"; 
     }); 

// Voilà 
print_r(socket_get_status($connection->connection)); 

Il Connection object stores the socket resource in a public property $connection:

public $connection; 
// ... 
@$this->connection = fsockopen($host, $port, $errNo, $errStr, $timeout);