host = $host; $this->port = $port; $this->setRecvTimeoutSec($recvTimeoutSec); $this->setRecvTimeoutUsec($recvTimeoutUsec); $this->setSendTimeoutSec($sendTimeoutSec); $this->setSendTimeoutUsec($sendTimeoutUsec); } /** * @param float $sendTimeoutSec */ public function setSendTimeoutSec(float $sendTimeoutSec) { $this->sendTimeoutSec = $sendTimeoutSec; } /** * @param float $sendTimeoutUsec */ public function setSendTimeoutUsec(float $sendTimeoutUsec) { $this->sendTimeoutUsec = $sendTimeoutUsec; } /** * @param float $recvTimeoutSec */ public function setRecvTimeoutSec(float $recvTimeoutSec) { $this->recvTimeoutSec = $recvTimeoutSec; } /** * @param float $recvTimeoutUsec */ public function setRecvTimeoutUsec(float $recvTimeoutUsec) { $this->recvTimeoutUsec = $recvTimeoutUsec; } /** * @param int $number */ public function setMaxWriteAttempts(int $number) { $this->maxWriteAttempts = $number; } /** * Connects the socket * * @access public * @return void */ public function connect() { if (!$this->isSocketDead()) { return; } if (empty($this->host)) { throw new \Kafka\Exception('Cannot open null host.'); } if ($this->port <= 0) { throw new \Kafka\Exception('Cannot open without port.'); } $this->stream = @fsockopen( $this->host, $this->port, $errno, $errstr, $this->sendTimeoutSec + ($this->sendTimeoutUsec / 1000000) ); if ($this->stream == false) { $error = 'Could not connect to ' . $this->host . ':' . $this->port . ' (' . $errstr . ' [' . $errno . '])'; throw new \Kafka\Exception($error); } stream_set_blocking($this->stream, 0); stream_set_read_buffer($this->stream, 0); $this->readWatcher = \Amp\onReadable($this->stream, function () { do { if (!$this->isSocketDead()) { $newData = @fread($this->stream, self::READ_MAX_LEN); } else { $this->reconnect(); return; } if ($newData) { $this->read($newData); $newData = true; } } while ($newData); }); $this->writeWatcher = \Amp\onWritable($this->stream, function () { $this->write(); }, array('enable' => false)); } /** * reconnect the socket * * @access public * @return void */ public function reconnect() { $this->close(); $this->connect(); } /** * get the socket * * @access public * @return void */ public function getSocket() { return $this->stream; } public $onReadable; /** * set on readable callback function * * @access public * @param \Closure $read * @return void */ public function SetOnReadable(\Closure $read) { $this->onReadable = $read; } /** * close the socket * * @access public * @return void */ public function close() { \Amp\cancel($this->readWatcher); \Amp\cancel($this->writeWatcher); if (is_resource($this->stream)) { fclose($this->stream); } $this->readBuffer = ''; $this->writeBuffer = ''; $this->readNeedLength = 0; } /** * checks if the socket is a valid resource * * @access public * @return boolean */ public function isResource() { return is_resource($this->stream); } /** * Read from the socket at most $len bytes. * * This method will not wait for all the requested data, it will return as * soon as any data is received. * * @param $data */ public function read($data) { $this->readBuffer .= $data; do { if ($this->readNeedLength == 0) { if (strlen($this->readBuffer) < 4) { return; } $dataLen = \Kafka\Protocol\Protocol::unpack(\Kafka\Protocol\Protocol::BIT_B32, substr($this->readBuffer, 0, 4)); $this->readNeedLength = $dataLen; $this->readBuffer = substr($this->readBuffer, 4); } if (strlen($this->readBuffer) < $this->readNeedLength) { return; } $data = substr($this->readBuffer, 0, $this->readNeedLength); $this->readBuffer = substr($this->readBuffer, $this->readNeedLength); $this->readNeedLength = 0; call_user_func($this->onReadable, $data, (int)$this->stream); } while (strlen($this->readBuffer)); } /** * Write to the socket. * * @param null $data */ public function write($data = null) { if ($data != null) { $this->writeBuffer .= $data; } $bytesToWrite = strlen($this->writeBuffer); $bytesWritten = @fwrite($this->stream, $this->writeBuffer); if ($bytesToWrite === $bytesWritten) { \Amp\disable($this->writeWatcher); } elseif ($bytesWritten >= 0) { \Amp\enable($this->writeWatcher); } elseif ($this->isSocketDead()) { $this->reconnect(); } $this->writeBuffer = substr($this->writeBuffer, $bytesWritten); } /** * check the stream is close * * @return bool */ protected function isSocketDead() { return !is_resource($this->stream) || @feof($this->stream); } }