2013-02-04 63 views
3

我試圖在PHP中使用SSL/TLS連接發送大量數據。它工作得很好,如果數據塊不是很大,或者如果我不使用TLS,但我需要什麼(2MiB附近),該fwrite功能顯示警告:在PHP中:OpenSSL錯誤消息:錯誤:1409F07F:SSL例程:SSL3_WRITE_PENDING:寫入重試錯誤

Warning: fwrite(): SSL operation failed with code 1. OpenSSL Error messages: error: 1409F07F: SSL routines: SSL3_WRITE_PENDING: bad write retry

相關的代碼我通過將客戶機連接L:

$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); 
    } 
} 

正如我所說的,我的代碼適用於小數據量或普通(非TLS)連接。我搜索了這個錯誤,並發現http://www.openssl.org/docs/ssl/SSL_write.html

SSL_write() will only return with success, when the complete contents of buf of length num has been written. This default behaviour can be changed with the SSL_MODE_ENABLE_PARTIAL_WRITE option of SSL_CTX_set_mode(3). When this flag is set, SSL_write() will also return with success, when a partial write has been successfully completed. In this case the SSL_write() operation is considered completed. The bytes are sent and a new SSL_write() operation with a new buffer (with the already sent bytes removed) must be started. A partial write is performed with the size of a message block, which is 16kB for SSLv3/TLSv1.

但我怎麼能做到這一點在PHP?

任何幫助,通過限制傳遞給fwrite()將8192串,防止FWRITE()警告的長度讚賞:)

回答

1

我發現我可以解決這個問題。

所以對於您的示例代碼我會嘗試改變SUBSTR()調用:

$buffer = substr($buffer, $len, 8192); 
-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)); 
}