Я использую самописный скрипт для отправки push-уведомлений в APNS с помощью PHP. Чтобы иметь возможность обрабатывать ошибки, я использую расширенный формат для push-уведомлений и хочу получать результаты из потока:

   // $apns = a stream_socket_client connection
   $apnsMessage  = pack('CNNnH*', 1, $i, $pnDetails['expiration_time'], 32, $pnDetails['token']);
   $apnsMessage .= pack('n', strlen($pnDetails['payload']));
   $apnsMessage .= $pnDetails['payload'];
   fwrite($apns, $apnsMessage);

   // Check for errors
   $errorResponse = @fread($apns, 6)
   if ($errorResponse != FALSE) {
    $unpackedError = unpack('Ccommand/CstatusCode/Nidentifier', $errorResponse);
   }

Я видел очень похожую практику в проекте apns-php, однако в моем случае скрипт всегда ждет неопределенно долго в строке fread, потому что он пытается прочитать данные, которых нет (Apple отправляет ответ только в случае ошибки) . Я искал способы узнать, есть ли какие-либо новые данные для чтения из потока TCP, однако я не смог их найти, и методы обратного вызова потока, доступные для HTTP-вызовов, также недоступны для "сырых" TCP-соединений.

Как я могу преобразовать свой скрипт, чтобы убедиться, что он вызывает fread только тогда, когда на самом деле есть данные для чтения? Как проект apns-php решает эту проблему (насколько я могу судить, они также просто вызывали fread)?

2
Robin 21 Фев 2011 в 21:50

2 ответа

Лучший ответ

Разобравшись, последний намек пришел от Эрвина. Хитрость заключалась в том, чтобы отключить блокировку с помощью stream_set_blocking, теперь мне просто нужно подождать некоторое время, прежде чем получать результаты с помощью fread, чтобы убедиться, что у Apple достаточно времени для ответа.

1
Robin 22 Фев 2011 в 16:33
1
Не могли бы вы обновить сообщение своим решением? Спасибо.
 – 
Miriam P. Raphael
2 Авг 2011 в 20:05
stream_set_blocking($this->socketName, 0);
 – 
junjie
23 Окт 2013 в 09:00
1
По какой-то причине у меня это не работает. Добавил эту строчку сразу после подключения, но на fread все равно зависает ..
 – 
Rihards
15 Апр 2015 в 11:03

Вы подключаетесь к нужному хосту ssl://feedback.push.apple.com:2196?

Они используют следующие вызовы для подключения и чтения данных:

stream_context_create -> stream_socket_client -> stream_set_blocking (0) -> stream_set_write_buffer (0) -> while (!feof($socket)) {} -> fread (8192) - > stream_select (с тайм-аутом)

0
Erwin 22 Фев 2011 в 10:16
Я думаю, вы неправильно поняли мой вопрос, я не говорю о службе обратной связи, я говорю о немедленной ошибке, возвращаемой, если push-уведомление имеет неправильный формат. См. Документацию об ошибках в расширенном формате здесь: bit.ly/f1kvv1
 – 
Robin
22 Фев 2011 в 14:56