У меня есть скрипт 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).
Единственный другой вариант — каким-то образом отслеживать эту строку на время ожидания (я не уверен, что это возможно) или каким-то образом передавать дескриптор сокета в другой процесс, который я могу запустить с помощью метода контроля времени ожидания.
Кто-нибудь знает, как это решить?
Вы можете попытаться установить тайм-аут в потоке, см. Руководство по PHP за stream_set_timeout($s)
Когда поток истекает, ключ ‘timed_out’ массива возвращается
by stream_get_meta_data () имеет значение 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));
?>
Обновление: это позволило оператору пройти мимо проблемы
ini_set('default_socket_timeout', 1);
Других решений пока нет …