Я не понимаю, как работает таймаут сокета и блокировка, и связаны ли эти два.
Это мой конструктор:
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);
}
При чтении из руководства время ожидания сокета устанавливает время ожидания в потоке. Мое первоначальное понимание состояло в том, что тайм-аут был пределом, до которого сокет будет пытаться что-то сделать, а после этого истечет время ожидания. Реальность, хотя, проверяя также состояние сокета с stream_get_meta_data()
, что я получаю следующее:
(
[timed_out] =>
[blocked] => 1
[eof] =>
[stream_type] => tcp_socket/ssl
[mode] => r+
[unread_bytes] => 0
[seekable] =>
)
Это происходит, когда я получаю первый ответ, для каждого последующего ответа значение timed_out
равно 1
.
Так как изначально мое время ожидания было 1s
Я думал, что сервер просто медленно реагировал, но увеличение значения до 50s
фактически увеличивало время ожидания каждого последующего запроса, как если бы таймаут был обязательным временем ожидания, а не "до" времени ожидания?
Также в связи с этим я пытался играть со статусом блокировки сокетов. Из руководства о блокировке сокетов я не смог получить много информации, так как он не объясняет, что означает, что поток блокируется или не блокируется. Погугление некоторых ресурсов, из того, что я понял, установив сокет в состояние блокировки, будет ожидать ответа сервера, и только после того, как ответ вернется, он продолжит другие запросы. Я думаю, что я не получил такое поведение, хотя.
После каждой записи я читаю. И запись, кажется, происходит намного быстрее, независимо от блокировки сокетов.
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");
}
Могу ли я подождать, чтобы проверить ответ и убедиться, что последующий запрос не сделан, если ответ не получен? sleep(1)
делает трюк быстрого исправления, но это не то, что я ищу. Повторный вызов функции receive()
также в некоторой степени помогает, но программа начинает вести себя странно, и я хотел бы избежать этого:
if (empty($response)) {
$this->receive();
return;
}
Кроме того, существует ли какая-либо взаимосвязь между временем ожидания сокета и состоянием блокировки?