Предотвратить закрытие потокового сокета в родительском сокете дочерней вилкой

У меня есть работник, который охватывает новые рабочие места с pcntl_fork()Я хотел бы повторно использовать одно и то же соединение у каждого ребенка без необходимости повторного подключения каждый раз у каждого ребенка, цель состоит в том, чтобы получить огромный прирост производительности.

  1. В родительском я подключаюсь к SMTP сервису, потом отключаю дочерний.
  2. Первый ребенок успешно может использовать поток SMTP и может отправить сообщение.
  3. Сокет автоматически закрывается, когда ребенок заканчивается. Я не вызываю никаких близких функций, ни деструкторов, вы можете увидеть в прикрепленном примере репо.
  4. После этого ни родитель, ни следующий ребенок не могут больше использовать открытый сокет.

Я хочу запретить номер 3. чтобы следующий ребенок мог повторно использовать сокет, без необходимости повторного подключения, поскольку вы знаете, что протокол SMTP болтлив и требует повторного подключения. Сервер SMTP может быть sendmail / sendgrid / Gmail, я пробовал несколько провайдеров, и проблема в моем PHP, а не в протоколе SMTP.

Я читал, что сигналы могут привести к закрытию потока. Есть ли способ, которым я могу предотвратить это.

какие у меня варианты?

я использую PHPMailer, Я удалил близко от деструктора. Я активировал SMTPKeepAlive но не помогло, как вы можете видеть в прикрепленном примере репо. Если имеет значение, я использую PHP 5.4

Обновление 1

Я добавил пример кода в этот публичный репозиторий: https://github.com/pentium10/php_stream_socket_test и вы можете проверить одноразовые входящие http://www.dispostable.com/inbox/test/

Вы можете найти выходные данные и SMTP-ответ в README-файле репо. Я подтверждаю, что, удаляя что-либо из вызова fork / child / exit, этот пример работает и отправляет несколько сообщений одно за другим.

3

Решение

После некоторых исследований в коде, который вы дали, похоже, ваша проблема возникает, когда вы включаете TLS.

Если вы отключите следующую строку:

$mail->SMTPSecure = 'tls';

Ваш код будет работать должным образом (как только ваш SMTP-сервер примет незащищенные соединения).

Так что это определенно не розетка и не вилка, но, вероятно нарушение протокола TLS.

Если вы попытаетесь отправить глагол RSET (например, вызов $mail->getSMTPInstance()->reset(); до вашего email() вызов), ошибка при отправке второго письма более понятна:

2014-11-04 00:23:18 SMTP ERROR: RSET command failed:
2014-11-04 00:23:18 SMTP NOTICE: EOF caught while checking if connected

Я не эксперт по криптозащите, поэтому я не могу идти дальше. Но я уверен, что ресурс, используемый stream_socket_client (и завернутый в stream_socket_enable_crypto) хранит некоторую контекстную информацию, необходимую для выполнения следующей транзакции TLS. После отправки электронного письма от первого дочернего элемента контекст ресурса актуален в памяти дочернего элемента, но не в родительской памяти. Поэтому, когда вы пытаетесь отправить другое письмо, используя старый контекст, TLS прерывается.

2

Другие решения

Других решений пока нет …