首页 > 解决方案 > PHP 套接字超时和阻塞

问题描述

我无法理解套接字超时和阻塞是如何工作的,以及这两者是否相互关联。

这是我的构造函数:

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

另外,套接字超时和阻塞状态之间是否有任何互连?

标签: phpsockets

解决方案


推荐阅读