Тайм-аут и блокировка сокета PHP - PullRequest
2 голосов
/ 30 июня 2019

Я не понимаю, как работает таймаут сокета и блокировка, и связаны ли эти два.

Это мой конструктор:

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;
    } 

Кроме того, существует ли какая-либо взаимосвязь между временем ожидания сокета и состоянием блокировки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...