PHP stream_socket_enable_crypto зависает бесконечно.В любом случае исправить? - PullRequest
0 голосов
/ 31 декабря 2018

У меня есть сценарий 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).

Единственный другой вариант - каким-то образом отслеживать эту строку на время ожидания (я не уверен, если это возможно) или каким-то образом передавать дескриптор сокета в другой процесс, который я могу запустить с помощьюметод контроля времени ожидания.

Кто-нибудь знает, как решить эту проблему?

1 Ответ

0 голосов
/ 31 декабря 2018

Вы можете попытаться установить тайм-аут в потоке, см. php manual для stream_set_timeout($s)

Когда истечет время ожидания потока, ключ 'timed_out' массивадля stream_get_meta_data () установлено значение TRUE, хотя сообщение об ошибке или предупреждение не генерируется.

Также найдено это в руководстве по PHP

Если кто-то озадачен, stream_set_timeout DOESНЕ работает для сокетов, созданных с помощью 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);

...