Why ssl: // shell approach doesn't work ...
It is not possible to use the ssl: // shell family to create non-blocking connections in PHP at this time, and the reason is simple:
To negotiate SSL / TLS acknowledgment, you must send and receive data.
You simply cannot duplicate information like this in a single operation (for example, what thread wrappers do) without blocking the execution of the script. And since PHP was originally designed to work in strictly synchronous environments (i.e., Blocking Web SAPIs, where each request has its own process), this locking behavior is a natural thing.
As a result, the ssl: // stream wrapper will not work the way you want, even if you set the STREAM_CLIENT_ASYNC_CONNECT flag. However, you can still use the PHP stream encryption capabilities in your non-blocking socket operations.
How to enable encryption in your non-blocking socket streams ...
SSL / TLS protocols run on top of the underlying transport protocol. This means that we only allow encryption protocols after TCP / UDP / etc. connection is established. As a result, we can first connect to the remote side using the async STREAM_CLIENT_ASYC_CONNECT flag, and then enable cryptography on the (now connected) socket using stream_socket_enable_crypto() .
A simple example without error handling
This example assumes that you understand how to use stream_select() (or equivalent lib notification information to work with sockets in a non-blocking way). Unable to handle potential socket errors.
<?php // connect + encrypt a socket asynchronously $uri = 'tcp://www.google.com:443'; $timeout = 42; $flags = STREAM_CLIENT_ASYNC_CONNECT; $socket = stream_socket_client($uri, $errno, $errstr, $timeout, $flags); stream_set_blocking($socket, false); // Once the async connection is actually established it will be "writable." // Here we use stream_select to find out when the socket becomes writable. while (1) { $w = [$socket]; $r = $e = []; if (stream_select($r, $w, $e, 30, 0)) { break; // the async connect is finished } } // Now that our socket is connected lets enable crypto $crypto = STREAM_CRYPTO_METHOD_TLS_CLIENT; while (1) { $w = [$socket]; $r = $e = []; if (stream_select($r, $w, $e, 30, 0)) { break; // the async connect is finished $result = stream_socket_enable_crypto($socket, $enable=true, $crypto); if ($result === true) { // Crypto enabled, we're finished! break; } elseif ($result === false) { die("crypto failed :("); } else { // handshake isn't finished yet. Do another trip around the loop. } } } // Send/receive encrypted data on $socket here
Return Values ββNote
It is very important to use equality === when checking the results of our cryptocurrency calls. As indicated in the relevant manual:
Returns TRUE on success, FALSE if negotiations failed, or 0 if there is not enough data, and you should try again (only for non-blocking sockets).
If we do not use === , we cannot distinguish between false and 0 .