How to check in PHP if the socket is still connected, if I don't have a socket handler?

I am using owlycode / streaming-bird composite package to call twitter stream API . The stream API opens a socket between your application and twitter to receive tweets with the specified keyword. In my case, the key word is hello.

Here is the code using owlycode / streaming-bird package:

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

My problem is when this connection is closed by an error, I cannot know it. So I canโ€™t connect to twitter again.

Is there anything in PHP that searches for open sockets based on their domain name?

Maybe something like

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

?

Note. I cannot use socket_get_status because I do not have a socket variable.

+8
linux php sockets twitter
source share
3 answers

It is not possible to check the status of a socket if you do not have access to the socket.

If you are looking for a workaround without touching the StreamBird code, you can create a class based on \OwlyCode\StreamingBird and then implement its connect method:

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

You can also create a class based on \OwlyCode\StreamingBird , which also has access to the stream. However, you will have to keep track of these threads because it is a factory method.

+4
source share

It looks like you can still use socket_get_status if you just make a little addition in the package itself.

These two functions are in the streamreader class, a socket handler is available here.

 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 the connection class, you have a socket handler so that you can capture the status of the socket when you try to read data from the socket. Below is a slightly modified read function

 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 = ''; } } } 
+1
source share

Considering the implementation of the StreamingBird class , you can easily create an instance of streamreader yourself, with full control over the connection:

 namespace \OwlyCode\StreamingBird; // Let instantiate the Oauth signature handler $oauth = new Oauth($consumerKey, $consumerSecret, $oauthToken, $oauthSecret); // Let 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)); 

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

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

All Articles