在PHP:OpenSSL的错误信息:错误:1409F07F:SSL例程:SSL3_WRITE_PEN

2019-07-19 06:20发布

我试图发送一个巨大的使用PHP SSL / TLS连接的数据量。 它工作得很好,如果数据块不是很大,或者如果我不使用TLS,但我需要什么(2MiB附近),该fwrite功能显示警告:

警告:FWRITE():SSL操作失败,代码1. OpenSSL的错误信息:错误:1409F07F:SSL例程:SSL3_WRITE_PENDING:不好写重试

我使用的是连接客户端的相关代码:

$cntxt = stream_context_create(array('ssl' => array('local_cert' => 'certificate.pem')));
$server = stream_socket_server('tls://127.0.0.1:8080', $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $cntxt);

// Wait for client connection //

$client = stream_socket_accept($server);
// Use non-blocking socket to allow answering many clients at a time
stream_set_blocking($client, 0);
$clients[] = $client;

当发送数据时,它添加到一个缓冲区,并且不时,这个函数被调用为每一个客户和链接缓存:

function trySend($client, &$buffer) {
    if (strlen($buffer)) {
        $len = fwrite($client, $buffer);
        $buffer = substr($buffer, $len);
    }
}

正如我所说的,我的代码适用于小数据ammount的或正常(非TLS)连接。 我搜索了这个错误,并发现http://www.openssl.org/docs/ssl/SSL_write.html :

SSL_write()将只与成功,当长度NUM的BUF的完整内容已经写入返回。 此默认行为可以用SSL_CTX_set_mode(3)的SSL_MODE_ENABLE_PARTIAL_WRITE选项进行更改。 当这个标志设置,SSL_write()也将返回成功,当部分写入已顺利完成。 在这种情况下SSL_write()操作被认为完成。 该字节发送,并用新的缓冲区(除去已经发送的字节)的新SSL_write()操作开始。 部分写入与消息块的大小,它是用于16kB的的SSLv3 /使用TLSv1执行。

但是,我怎么能在PHP这样做呢?

任何帮助表示赞赏:)

Answer 1:

我发现我可以通过限制传递给fwrite()将8192串,防止FWRITE()警告的长度解决这个问题。

所以对于您的示例代码我会尝试改变SUBSTR()调用:

$buffer = substr($buffer, $len, 8192);


Answer 2:

解决的办法是:

$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
try {                           
$result = fwrite($fp, $msg, strlen($msg));
}
catch (Exception $ex) {
sleep(1); //sleep for 5 seconds
$result = fwrite($fp, $msg, strlen($msg));
}


文章来源: In PHP: OpenSSL Error messages: error: 1409F07F: SSL routines: SSL3_WRITE_PENDING: bad write retry