php - 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;
}
另外,套接字超时和阻塞状态之间是否有任何互连?
解决方案
推荐阅读
- javascript - How to implement vue package
- c# - C# WPF XAML: Layout issues with dynamic stretching, statusbar and horizontal datagrid expansion
- r - 使用 rmarkdown - 和 scale_down 将大表放入 pdf
- pandas - 如何将一行整数附加到熊猫中跨多个列的单个列表中
- javascript - 用户与 iframe 交互后重定向主页
- c# - 如何使用单独项目中的 MVC 视图?
- reactjs - 为什么我的内容没有显示在网格中?(反应.js)
- powerbi - 有没有办法使用 MDX 查询将数据从 HFM 数据库加载到 powerbi 中?
- java - Java流按某个值对列表进行排序,然后按另一个值对重复项进行排序
- javascript - getJSON API 适用于 localhost 但不适用于网络服务器