我无法理解套接字超时和阻塞的工作方式,以及这两者是否互连。
这是我的构造函数:
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);
}
从socket 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
实际上会增加每个后续请求的等待时间,就好像超时是强制性等待一样时间,不是“最多”的等待时间?
关于这一点,我尝试使用套接字阻止状态。从关于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");
}
是否有一种方法可以等待检查响应,并确保没有后续请求,除非获取了响应? sleep(1)
可以快速解决问题,但不是我想要的。再次调用receive()
函数在某种程度上也可以解决问题,但是程序开始表现出奇怪的现象,我想避免这种情况:
if (empty($response)) {
$this->receive();
return;
}
此外,套接字超时和阻塞状态之间是否存在任何互连?