fwrite(): операция SSL не удалась с кодом 1. Сообщения об ошибках OpenSSL:\nerror:1409F07F:процедуры SSL:SSL3_WRITE_PENDING:неудачная повторная попытка записи в PHP

У меня есть те же вопросы в stackoverflow, и я перепробовал все ответы, но не помог. Я не понимаю, в чем ошибка.

Вот моя функция, которую я использую:

function sendRegistryNotification($message, $deviceToken, $deviceType, $batchcount)
        {               
            $message=$message;
            $batchcount=$batchcount;            
            $path=ABSPATH.'api'.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR.'Certificates2.pem';
            $deviceType = strtolower($deviceType);
            switch ($deviceType) {
                case 'ios':
                   $pemPath = $path; // replace with the path to PEM file
                   $ctx = stream_context_create();
                   stream_context_set_option($ctx, 'ssl', 'local_cert', $pemPath);

                   $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195',
                       $err,
                       $errstr,
                       60,
                       STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,
                       $ctx);
                       // Create the payload body
                       $body['aps'] = array(
                           'badge' => +$batchcount,
                           'alert' => $message,
                           'sound' => 'default'
                       );
                       $payload = json_encode($body);
                       // Build the binary notification
                       $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
                       // Send it to the server
                       $result = fwrite($fp, $msg, strlen($msg));
                       var_dump($result);
                       if (!$result)
                       {
                           fclose($fp);
                           return false;
                       }                                       
                       else
                       {
                           fclose($fp);
                           return true;                  
                       }  
                    break;
                case 'android':
                   $message = array("message" => $message,'title'=> 'eyLog','msgcnt'=>$batchcount);
                   // Set POST variables
                   $url = 'https://android.googleapis.com/gcm/send';

                   $fields = array(
                       'registration_ids' => array($deviceToken),
                       'data' => $message,
                   );
                   $headers = array(
                       'Authorization: key='.'AIzaSyDud68-R31c9SPq4dXZblt0JBPi4TBaneQ', // Key For eylog App
                       'Content-Type: application/json'
                   );
                   // Open connection
                   $ch = curl_init();
                   // Set the url, number of POST vars, POST data
                   curl_setopt($ch, CURLOPT_URL, $url);
                   curl_setopt($ch, CURLOPT_POST, true);
                   curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                   // Disabling SSL Certificate support temporarly
                   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                   curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
                   // Execute post
                   $result = curl_exec($ch);
                   //var_dump($result);
                   if ($result === FALSE) {
                    //   die('Curl failed: ' . curl_error($ch));
                   }
                   // Close connection
                   curl_close($ch);
                   return TRUE;
                    break;
            }
            return true;
        }

Вот ошибка, которую я получаю:

{
    "status": "failure",
    "uniquediary_id": "14407503971",
    "message": "fwrite(): SSL operation failed with code 1. OpenSSL Error messages:\nerror:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry"
}

Я не понимаю, почему это происходит. и код выдает только ошибку на сервере, на моем локальном хосте он работает нормально


person Prashant    schedule 02.09.2015    source источник


Ответы (3)


Когда вы пытаетесь писать в сокет. Если что-то пойдет не так, fwrite вернет false или 0 (в зависимости от версии php) в качестве возвращаемого значения. Когда это происходит, вы должны управлять этим.

Для вышеуказанной проблемы причина довольно проста: когда SSL_Write возвращается с SSL_ERROR_WANT_WRITE или SSL_ERROR_WANT_READ, вам нужно снова повторить вызов SSL_write с теми же параметрами после того, как условие выполнено (чтение/запись доступны в сокете).

Вызов его с другими параметрами приведет к ошибке повторной попытки записи 1409F07F.

person Santosh Jagtap    schedule 15.09.2015

Я получаю эту ошибку много раз. Чтобы решить эту проблему, непосредственно перед fwrite() я добавил sleep(5);.

Теперь все запросы возвращаются с успехом.

person Nico    schedule 14.04.2016
comment
Я прочитал ответы на 4 разные версии этой ошибки на StackOverflow. Это тот, который исправил это для меня. - person Phil McCarty; 03.01.2017

Спасибо за ответ, я нашел аналогичные решения в Google, которые вы должны снова написать в сокет. В моем случае код выдавал исключение, поэтому я справляюсь с этим. Итак, теперь я делаю это так

$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

// Send it to the server
try {                           
    $result = fwrite($fp, $msg, strlen($msg));
}
catch (Exception $ex) {
    // try once again for socket busy error (fwrite(): SSL operation failed with code 1.
    // OpenSSL Error messages:\nerror:1409F07F:SSL routines:SSL3_WRITE_PENDING)
    sleep(5); //sleep for 5 seconds
    $result = fwrite($fp, $msg, strlen($msg));
    if ($result)
    {
        return true;
    }
    else {
        return false;
    }
}

Теперь он не выдает эту ошибку в большинстве случаев. Я обнаружил, что это происходит, когда сокет занят, поэтому я пытаюсь снова написать через 5 секунд. Так что я думаю, что это не должно повториться. Он еще не запущен, но в ходе нашего тестирования мы больше не обнаружили эту проблему. Можете ли вы предположить, что я иду в правильном направлении? Когда этот код будет запущен, тогда будет огромное количество push-уведомлений, тогда он будет работать нормально или у вас есть какое-то другое решение? Спасибо за помощь :)

person Prashant    schedule 09.10.2015
comment
@Prashant, у меня такая же проблема. Я попробовал ваш ответ, но он не работает для меня. я получил ошибку, но выполнение не переходит в блок catch. - person Dhara; 08.09.2016
comment
тогда вы, должно быть, делаете что-то не так.. это базовый php, если есть какая-либо ошибка, она должна быть в блоке catch.. опубликуйте свой код, чтобы другие могли его проверить :) - person Prashant; 27.09.2016