<?php
$CRLF = "\r\n";
$socket = @fsockopen("smtp.qq.com", 25, $errno, $errstr, 30) or die("创建Socket链接时出错.");
@stream_set_blocking($socket, 1);
@stream_set_timeout($socket, 5);
$msg = fgets($socket);  // 输出 220 esmtp4.qq.com Esmtp QQ Mail Server
if(strpos($msg, "220")===0) {
  if(fwrite($socket, "EHLO ".$_SERVER['SERVER_NAME'].$CRLF)!==FALSE) {
    // 使用 EHLO 命令的话,返回如下信息
    // 250-esmtp4.qq.com
    // 250-PIPELINING
    // 250-SIZE 52428800
    // 250-AUTH LOGIN PLAIN
    // 250-AUTH=LOGIN
    // 250 8BITMIME
    $msg = fgets($socket);
    if(strpos($msg, "250")===0) {
      if(fwrite($socket, "AUTH LOGIN".$CRLF)!==FALSE) {
        // 输出的是 250-PIPELINING
        // 想要输出的是 334 VXNlcm5hbWU6
        $msg = fgets($socket);
        echo $msg;
      }
    }
  }
}
fclose($socket);
?>
描述如上面的代码
如果返回的有多行,则每次fgets只能取一行
如果知道行数的话,倒是可以跳过N行
但关键是行不固定,而且也无法用 feof 函数来判断行数
在网上看到一个
// 原文地址 http://baiyuxiong.iteye.com/blog/758754
while( ($line=trim(fgets($conn))) != "" ) {  
  echo "head读之前:".(microtime(true)-$start)."<br>";
  $header.=$line;
  if(strstr($line,"Content-Length:")) {
    list($cl,$len)=explode(" ",$line);
  }
  echo "head读之后:".(microtime(true)-$start)."<br>";
}
但测试了无效,和用 feof 函数同样
有其他办法吗?

解决方案 »

  1.   

    string fgets ( int $handle [, int $length ] )
    从 handle 指向的文件中读取一行并返回长度最多为 length - 1 字节的字符串。碰到换行符(包括在返回值中)、EOF 或者已经读取了 length - 1 字节后停止(看先碰到那一种情况)。如果没有指定 length,则默认为 1K,或者说 1024 字节。
    $msg=fgets($socket, 1024);
    这样每次就读取1KB数据!
    读取完以后把接收的数据分割成数组之后foreach判断一下就行!
      

  2.   

    没用,不关设置多大,它每次就获取一行非加密格式的话,等待时间可以控制
    如果是SSL或者TSL的话,直接卡住...
    非加密格式的话,等到PHP的运行超时时间的话,就会返回警告
    但如果是SSL或者TSL的话,就直接卡在那...只好重启服务...
      

  3.   

    <?php
    $CRLF = "\r\n";
    $socket = @fsockopen("smtp.qq.com", 25, $errno, $errstr, 30) or die("创建Socket链接时出错.");
    @stream_set_blocking($socket, 1);
    @stream_set_timeout($socket, 5);
    $msg = fgets($socket);  // 输出 220 esmtp4.qq.com Esmtp QQ Mail Server
    if(strpos($msg, "220")===0) {
      if(fwrite($socket, "EHLO ".$_SERVER['SERVER_NAME'].$CRLF)!==FALSE) {
        // 使用 EHLO 命令的话,返回如下信息
        // 250-esmtp4.qq.com
        // 250-PIPELINING
        // 250-SIZE 52428800
        // 250-AUTH LOGIN PLAIN
        // 250-AUTH=LOGIN
        // 250 8BITMIME
        $msg = fgets($socket);
        if(strpos($msg, "250")===0) {
          if(fwrite($socket, "AUTH LOGIN".$CRLF)!==FALSE) {
            // 输出的是 250-PIPELINING
            // 想要输出的是 334 VXNlcm5hbWU6
    $msg = fgets($socket);

    // 这样不就跳过了?
            while(strpos($msg, "334")!==0) {
    $msg = fgets($socket);
    }
    echo $msg;
          }
        }
      }
    }
    fclose($socket);
      

  4.   


    如果你不明白smtp通信协议的规范的话,你是没有办法写这样的程序的!
      

  5.   

    我的意思是说
    如果服务器在接收到AUTH LOGIN命令后,并不是返回334
    而是其他的代码,比如说该SMTP服务器根本就不需要登录的话,发送AUTH LOGIN命令后肯定不会返回334代码的
      

  6.   


    我要通信 ok(或者你好,欢迎等其他内容)那么你只有拿到ok才能进行下一步我叫xx ,这时有个分支下一步 or 有钥匙吗 or 结束(或者你要什么帮助,在说一遍)那么你肯定要接受到内容跟(继续 or 没有听清 or 结束)要对比,直到符合这3种情况时,进行下一步动作,如果不是这3种情况,要么等待超时,要么就继续等待,逻辑已经规定了(继续 or 没有听清 or 结束)这3种情况才能下一步所以说,你接受反馈信息时,直到每一步的反馈信息是符合要求的,你才能进下一步,每一步你都要知道什么时符合要求,不符合要求就要等待符合要求为止!
      

  7.   

    socket_read可以使用这个函数试试;这个是读取最大字节数的数据流