2016-04-13 7 views
8

Ich verwende ein Composer-Paket owlycode/streaming-bird, um twitter stream API zu rufen. Die Stream-API öffnet einen Socket zwischen Ihrer App und Twitter, um Tweets mit einem bestimmten Keyword zu erhalten. In meinem Fall ist das Schlüsselwort "Hallo".Wie PHP einchecken, wenn ein Socket immer noch verbunden ist, wenn ich nicht den Socket-Handler habe?

Hier ist der Code mit owlycode/Streaming-Vogel-Paket:

<?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"; 
     }); 
    ?> 

Mein Problem ist, wenn diese Verbindung durch Fehler geschlossen ist, ich bin nicht in der Lage, das wissen. Ich kann also nicht wieder mit Twitter verbinden.

Gibt es irgendetwas in PHP, das offene Sockets basierend auf ihrem Domain-Namen sucht?

Vielleicht so etwas wie

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

?

Hinweis: Ich kann socket_get_status nicht verwenden, da ich die Socket-Variable nicht habe.

+0

Es [mir sieht] (https://github.com/OwlyCode/StreamingBird/blob/master/src/StreamReader.php#L80) als würde es den Socket immer wieder verbinden, wenn die Verbindung verloren ist. – miken32

+0

Wenn man sich die Inline-Dokumentation anschaut, sieht es so aus, als wäre @ miken32 korrekt. Ich denke, das Problem ist die Zeit, die man braucht, um einen Verbindungsverlust zu erkennen ... zum Beispiel: wenn das Timeout standardmäßig 1 Minute beträgt ... dann hast du es 1 Minute des Streams verloren – edhurtig

+0

Obwohl es eine schlechte Lösung ist ... es lohnt sich aus anderen Gründen in stream_set_timeout ($ stream, $ Sekunden) zu suchen. http://php.net/manual/en/function.stream-set-timeout.php – edhurtig

Antwort

1

Es sieht so aus, als könnten Sie socket_get_status verwenden, wenn Sie nur eine kleine Erweiterung im Paket selbst machen.

Diese beiden Funktionen befinden sich in der Streamreader-Klasse. Der Socket-Handler ist hier verfügbar.

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 Verbindung Klasse haben Sie die Socket-Handler zur Verfügung, so können Sie Socket-Status greifen, wenn versuchen, Daten aus der Fassung zu lesen. Nachfolgend finden Sie eine leicht modifizierte Lesefunktion

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

Es gibt keine Art und Weise ist Socket-Status zu überprüfen, wenn Sie keinen Zugriff auf die Buchse haben.

Wenn Sie dieses Problem zu umgehen ist ohne StreamBird des Code zu berühren, dann können Sie eine Klasse machen, basierend auf \OwlyCode\StreamingBird, dann implementieren seine connect Methode:

<?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(); 

Sie können auch eine Klasse machen basierend auf \OwlyCode\StreamingBird, welches auch Zugriff auf den Stream hat. Allerdings müssen Sie diese Streams im Auge behalten, da es sich um eine Factory-Methode handelt.

1

am implementation of class StreamingBird Sehen, sehen Sie Sie bequem die Stream Instanz erstellen können sich selbst, mit voller Kontrolle über die Verbindung:

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)); 

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

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