首页 > 解决方案 > PHP stream_socket_enable_crypto 无限期挂起。无论如何要修复?

问题描述

我有一个 PHP 脚本,用于将电子邮件发送到我的一个站点中的时事通讯列表。

该脚本使用 STARTTLS 进行加密连接,使用以下行来建立 SSL 握手:

stream_set_timeout($s, 35, 0);                                  
if(false == stream_socket_enable_crypto($s, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)){
    $msg = "452 failed on tls connection";
} else {
    $in_tls = true;
}

套接字 $s 设置为阻塞,并在发出 STARTTLS 命令后已连接到远程服务器,并准备在此阶段启动 TLS 握手。如您所见,我在握手之前使用了stream_set_timeout。根据 PHP 文档,它应该在 X 秒后中止握手,但它似乎并没有影响它。

现在这段代码大部分时间都可以工作,但有时我会遇到 TLS 握手会无限期阻塞的服务器,导致脚本挂起。

我试过研究非阻塞解决方案,但它们都不适用于我的 PHP 版本(我使用 v5.1.6)。

唯一的另一种选择是以某种方式监视这条线的超时(我不确定这是否可能),或者以某种方式将套接字句柄转移到另一个我可以使用超时控制方法运行的进程。

任何人都知道如何解决这个问题?

标签: phpsocketsstarttls

解决方案


您可以尝试在流上设置超时,请参阅php手册stream_set_timeout($s)

当流超时时,stream_get_meta_data() 返回的数组的 'timed_out' 键设置为 TRUE,但不会生成错误/警告。

在 PHP 手册上也找到了这个

如果有人感到困惑,stream_set_timeout 不适用于使用 socket_create 或 socket_accept 创建的套接字。请改用 socket_set_option。

Instead of:
<?php
stream_set_timeout($socket,$sec,$usec);
?>

Use:
<?php
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>$sec, 'usec'=>$usec));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>$sec, 'usec'=>$usec));
?>

更新:这允许 OP 解决问题 ini_set('default_socket_timeout', 1);


推荐阅读