diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2021-03-03 17:46:32 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2021-03-03 17:46:32 +0300 |
commit | 3bd1d7b536581ee5eb238c64b2ac9a9452da870d (patch) | |
tree | b65a3e1a4747a273694a63cedb505229634c0802 | |
parent | 0336bc61bf8a6c1da99fba5918f0c08be864719e (diff) |
use socket_* family of functions
-rw-r--r-- | composer.json | 3 | ||||
-rw-r--r-- | src/Client.php | 61 |
2 files changed, 51 insertions, 13 deletions
diff --git a/composer.json b/composer.json index 6777be3..9c73bcc 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ }, "require": { "php": ">=7.0", - "ext-json": "*" + "ext-json": "*", + "ext-sockets": "*" } } diff --git a/src/Client.php b/src/Client.php index a56f499..b4628ca 100644 --- a/src/Client.php +++ b/src/Client.php @@ -31,12 +31,15 @@ class Client { $this->host = $host; $this->password = $password; - $this->sock = fsockopen($this->host, $this->port); - if (!$this->sock) - throw new Exception("Failed to connect to {$this->host}:{$this->port}"); + if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) + throw new Exception("socket_create() failed: ".$this->getSocketError()); + + $this->sock = $socket; + + if ((socket_connect($socket, $host, $port)) === false) + throw new Exception("socket_connect() failed: ".$this->getSocketError()); - // 0 is reserved - $this->lastOutgoingRequestNo = mt_rand(1, self::REQUEST_NO_LIMIT); + $this->lastOutgoingRequestNo = mt_rand(1 /* 0 is reserved */, self::REQUEST_NO_LIMIT); } /** @@ -110,11 +113,22 @@ class Client { /** * @param Message $message + * @throws Exception */ public function send(Message $message) { - $serialized = $message->serialize(); - fwrite($this->sock, $serialized . self::EOT); + $data = $message->serialize() . self::EOT; + $remained = strlen($data); + + while ($remained > 0) { + $result = socket_write($this->sock, $data); + if ($result === false) + throw new Exception(__METHOD__ . ": socket_write() failed: ".$this->getSocketError()); + + $remained -= $result; + if ($remained > 0) + $data = substr($data, $result); + } } /** @@ -124,15 +138,27 @@ class Client { */ public function recv(int $request_no = -1) { - $messages = []; + $recv_buf = ''; $buf = ''; - while (!feof($this->sock)) { - $buf .= fread($this->sock, 1024); + $buflen = 0; + + while (true) { + $result = socket_recv($this->sock, $recv_buf, 1024, 0); + if ($result === false) + throw new Exception(__METHOD__ . ": socket_recv() failed: " . $this->getSocketError()); + + // peer disconnected + if ($result === 0) + break; + + $buf .= $recv_buf; + $buflen = strlen($buf); - if ($buflen > 0 && $buf[$buflen-1] == self::EOT) + if ($buf[$buflen-1] == self::EOT) break; } + $messages = []; $offset = 0; $eot_pos = 0; do { @@ -340,8 +366,19 @@ class Client { if (!$this->sock) return; - fclose($this->sock); + socket_close($this->sock); $this->sock = null; } + /** + * @return string + */ + protected function getSocketError() + { + $sle_args = []; + if ($this->sock !== null) + $sle_args[] = $this->sock; + return socket_strerror(socket_last_error(...$sle_args)); + } + }
\ No newline at end of file |