防止在父级中打开的流套接字由子fork关闭

时间:2014-10-28 15:53:26

标签: php sockets cryptography signals parent-child

我有一个跨越pcntl_fork()新工作的工作者,我想在每个孩子中重复使用相同的连接,而不需要每个孩子每次重新连接,目标是获得巨大的性能提升。

  1. 在父级中,我连接到SMTP服务,然后分叉一个孩子。
  2. 第一个子节点成功使用SMTP流并可以发送消息。
  3. 当孩子结束时,套接字会自动关闭。我没有调用任何关闭函数既不是析构函数,也可以在附加的repo示例中看到。
  4. 此后,父母和下一个孩子可以再使用已打开的套接字。
  5. 我想阻止编号3.这样下一个孩子就可以重用套接字而无需重新连接,因为你知道SMTP协议很繁琐,需要时间重新连接。 SMTP服务器可能是sendmail / sendgrid / Gmail,我试过多个提供商,问题出在我的PHP而不是SMTP协议中。

    我读到信号可能会导致流关闭。有没有办法可以防止这种情况发生。

    我的选择是什么?

    我正在使用PHPMailer,我删除了close from destructor。我已激活SMTPKeepAlive,但没有帮助,正如您在附加的回购示例中所看到的那样。如果我使用的是PHP 5.4

    更新1

    我已将示例代码添加到此公共仓库:https://github.com/pentium10/php_stream_socket_test,您可以在http://www.dispostable.com/inbox/test/

    检查可处置的收件箱

    您可以在repo的README文件中找到输出和SMTP响应。我确认从fork / child / exit调用中删除了任何内容,该示例可以工作并一个接一个地发送多个消息。

1 个答案:

答案 0 :(得分:2)

在对您提供的代码进行一些调查后,看起来您的问题出现在启用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会中断。