I am failing to understand how socket timeout and blocking works, and whether those two are interconnected.
This is my constructor:
public function __construct(Options $options)
{
$this->connection = stream_socket_client($options->fullSocketAddress());
stream_set_blocking($this->connection, true);
stream_set_timeout($this->connection, 0, $this->timeout);
}
Reading from the manual, socket timeout sets a timeout on a stream. My initial understanding was that the timeout was a limit up to which point the socket will try to do something, and after that will time out. The reality though, when checking also the socket status with stream_get_meta_data() that I get the following:
(
[timed_out] =>
[blocked] => 1
[eof] =>
[stream_type] => tcp_socket/ssl
[mode] => r+
[unread_bytes] => 0
[seekable] =>
)
This is happening when I get the first response, for every subsequent response the timed_out value is 1.
Since initially my timeout value was 1s I thought the server was just slow to respond, but increasing the value to 50s actually increased waiting time of each subsequent request as if the timeout was a mandatory waiting time, not the "up to" waiting time?
Also with regards to that I tried playing with socket blocking status. From the manual about socket blocking I couldn't get much info as it is not explaining what does it mean for a stream to be blocking or non blocking. Googling some resources, from what I could understand setting a socket to a blocking status would wait for server response, and only after the response got back, it would continue with other requests. I think that I didn't get that behaviour though.
Upon each write, I am doing a read. And writing seems to happen much faster independently of socket blocking.
public function send(string $xml)
{
try {
fwrite($this->connection, $xml);
$this->options->getLogger()->logRequest(__METHOD__ . '::' . __LINE__ . " $xml");
$this->checkSocketStatus();
} catch (Exception $e) {
$this->options->getLogger()->error(__METHOD__ . '::' . __LINE__ . " fwrite() failed " . $e->getMessage());
return;
}
$this->receive();
}
public function receive()
{
$response = '';
while ($out = fgets($this->connection)) {
$response .= $out;
}
if (empty($response)) {
return;
}
$this->responseBuffer->write($response);
$this->options->getLogger()->logResponse(__METHOD__ . '::' . __LINE__ . " $response");
}
Is there a way I can wait to check for response, and to make sure no subsequent request is made unless response is fetched? sleep(1) does the quick fix trick, but is not what I'm looking for. Calling the receive() function once again also does the trick to some extent, but the program starts behaving strange and I would like to avoid it:
if (empty($response)) {
$this->receive();
return;
}
Also, is there any interconnection between socket timeout and blocking status?