如何通过fsockopen / fwrite / fread / fgets

时间:2016-04-30 23:15:55

标签: php smtp

我想知道如何通过fsockopen/fwrite/fread/fgets等与PHP服务器正确地进行交互。主要问题似乎是您不知道何时停止阅读命令已发送。

我分析了一些公开的PHP脚本,但没有看到正确的方法。我的下面的脚本对IMO做了两件事:

  • 它读取服务器返回的所有行。例如,getmxrr.php处显示的用户脚本只能读取2行...(for($i=0;$i<2;$i++) $s.=fgets($fp, 1024);
  • 它补偿了缺乏明确的&#34;我做完了&#34;通过设置流超时来自服务器的信号。

然而,这很慢。在每个命令之后,您需要等待2秒才能启动超时。

// error handling and such missing on purpose to keep it short
$host = "some-MX-host.com";

$commands = array();
$commands[] = "EHLO microsoft.com\r\n";
$commands[] = "MAIL FROM:<>\r\n";
$commands[] = "RCPT TO:<foo@some-MX-host.com>\r\n";

@$fp = fsockopen($host, 25);
stream_set_timeout($fp, 2);

foreach ($commands as $command) {
  echo $command;
  fwrite($fp, $command);
  while ($line = fgets ($fp)) {
    print $line;
  }
}

fclose($fp);

如何改进?

旁注...某些服务器对RCPT TO:<foo@some-MX-host.com>中的某些电子邮件地址的响应速度非常慢(通常由于打字错误而无效)。因此,超时2秒通常不够好。因此,为了获得更好的性能,您希望大多数命令(例如1秒)的超时时间更短,RCPT TO(例如5秒)的超时时间更长。这可能会提高性能,但会使实施变得复杂。

更新2016-05-02

以下修改将减少全局超时,但如果服务器需要一些额外的时间用于某些命令,则仍会等待更长时间。我对这种表现感到非常满意,但我仍然怀疑它没有更优雅。

stream_set_timeout($fp, 1);

foreach ($commands as $command) {
  echo $command;
  fwrite($fp, $command);
  // Wait at most 10 * timeout for the server to respond.
  // In most cases the response arrives within timeout time and, therefore, there's no need to wait any longer in such
  // cases. However, there are cases when a server is slow to respond. This for-loop will give it some slack.
  for ($i = 0; $i < 10; $i++) {
    $response = "";
    while ($line = fgets($fp)) {
      $response .= $line;
    }
    // Only continue the for-loop if the server hasn't sent anything yet.
    if ($response != "") {
      break;
    }
  }
  echo $response;
}

0 个答案:

没有答案