使用 SSL 的流式套接字

Posted

技术标签:

【中文标题】使用 SSL 的流式套接字【英文标题】:Stream socket with SSL 【发布时间】:2016-10-19 08:02:59 【问题描述】:

我在 php 5.6 中遇到了流套接字和 SSL 的问题。 似乎 SSL 正在缓冲输出。 在下面的示例中,“ehlo”命令被忽略(服务器没有响应)。 但是当在“ehlo”之后发送其他内容时,例如在另一个对fwrite 的调用中换行,服务器发送响应。

$errno = '';
$errstr = '';
$timeout = 5;
$streamContext = stream_context_create();
$host = 'ssl://smtp.some.server.com:465';
$stream = stream_socket_client($host, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
stream_set_blocking($stream, 1);
stream_set_timeout($stream, $timeout);
stream_set_write_buffer($stream, 0);

$fgets = fgets($stream);
print_r($fgets);

fwrite($stream, "ehlo [127.0.0.1]\r\n");

$response = '';
do 
    $line = fgets($stream);
    $response .= $line;
 while (null !== $line && false !== $line && ' ' != $line3);

print_r($response);

fclose($stream);

我收到了回复:

220 epicserver.net.pl ESMTP IdeaSmtpServer v0.80.2 ready.

(来自第一个print_r)。

但是当行后:fwrite($stream, "ehlo [127.0.0.1]\r\n"); 我添加了额外的套接字写入:fwrite($stream, "\n"); 输出正常:

220 epicserver.net.pl ESMTP IdeaSmtpServer v0.80.2 ready.
250-epicserver.net.pl Hello ip-166-242.pl [94.183.162.232], pleased to meet you
250-PIPELINING
250-ENHANCEDSTATUSCODES
250-SIZE
250-8BITMIME
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250 HELP

我尝试使用 stunnel 来检查它是否是 PHP SSL 包装问题,当我将 $host 更改为 $host = 'localhost:110;'(我的 stunnel 配置)时,一切正常(不添加特殊的 fwrite 方法)。

有人遇到过这个问题吗?

【问题讨论】:

例如swiftmailer.org 出现同样的问题?如果没有,您可以将该实现与您的实现进行比较。 是的,测试代码取自 swiftmailer 实现。 那么,如果你使用带有 ssl://smtp.some.server.com:465 的 swiftmailer,它就不起作用,因为它没有完成握手? 连接已建立,服务器提示我准备就绪。我可以看到命令已发送,但服务器响应倒数第二个命令(最后一个似乎已缓冲)。完全相同的问题出现在我的示例代码中(流上下文缓冲区的东西?)。 握手完成了吗?或者我认为您需要通知之间存在延迟 【参考方案1】:

用此代码替换第一个 fget,以确保 fget 正确理解行终止:

$fgets = '';
while (is_resource($stream) && !feof($stream)) 
  $fgets .= fgets($stream); 

【讨论】:

以上是关于使用 SSL 的流式套接字的主要内容,如果未能解决你的问题,请参考以下文章

如何使用来自网络套接字的网络音频 API 流式传输音频块?

使用 Web 套接字和 ReactJs 流式传输每个文件的内容

如何在 iOS swift 中使用 UDP 套接字流式传输音频?

使用 AVFoundation 在 iOS 上播放套接字流式传输的 h.264 电影

C错误从流式套接字读取数据包

流式套接字(SOCK_STREAM),数据报套接字 (SOCK_DGRAM) 的比较