2014-10-28 2 views
3

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

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

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

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

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

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

Update 1

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

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

+0

Сокет не закрыт, пока все процессы, открывающие его, не закрывают его. Номер 4 не существует, родитель должен все еще использовать сокет. – Barmar

+0

Направляет ли ребенок команду «QUIT» в соединение? Это заставит сервер закрыть соединение. – Barmar

+0

Он не отправляет команду QUIT, я проверял использование sleep(), и соединение закрывается, когда ребенок завершает работу. – Pentium10

ответ

2

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

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

$mail->SMTPSecure = 'tls'; 

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

Так что это, безусловно, не сокет, ни вилки проблема, но нарушение протокола, вероятно ДУС. (., Например, позвонив $mail->getSMTPInstance()->reset(); до вашего email() вызова)

Если вы пытаетесь отправить глагол RSET, ошибка при отправке второй почты понятнее:

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 

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

+0

Вам не хватает exit() в дочернем элементе после: 'socket_close ($ sock) или err ('close');' to correct закрыть разветвленный процесс и не оставлять позади. – Pentium10

+0

Я реализовал ваш код, и у меня все еще есть проблемы. См. Мой связанный пример в репо. – Pentium10

+0

@ Pentium10: Это убедительное доказательство того, что эта проблема связана с сервером. – alk