我们正在使用修改版的easy-apns来发送我们的推送消息。使用增强的推送消息格式,如果发生错误,Apple 服务器会做出响应,如果一切顺利,则不执行任何操作。
问题是我们必须在每条消息发送后等待错误一段时间。例如,如果我们在 1 秒后没有收到响应,我们假设一切正常。
对于 20000 条推送消息,这需要的时间太长了。有什么方法可以让我以更快的方式收听错误吗?例如发送到 1000 个设备然后监听错误?如果连接关闭会发生什么,我还能读取错误响应吗?
理想的是某种异步读写,但我认为这是不可能的。
下面是对应的代码:
$fp = $this->connect();
$expiry = time()+60*60;
// construct message
$msg = chr(1).pack("N",$batchid).pack("N",$expiry).pack("n",32).pack('H*',$devicetoken).pack("n",strlen($payload)).$payload;
// send message to Apple
$fwrite = fwrite($fp, $msg);
if(!$fwrite) {
// connection has been closed
$this->disconnect();
throw new Exception("Connection closed");
} else {
// read response from Apple
// Timeout. 1 million micro seconds = 1 second
$tv_sec = 1;
$tv_usec = 0;
$r = array($fp);
$we = null; // Temporaries. "Only variables can be passed as reference."
// PROBLEM: this method waits for $tv_sec seconds for a response
$numChanged = stream_select($r, $we, $we, $tv_sec, $tv_usec);
if( $numChanged === false ) {
throw new Exception("Failed selecting stream to read.");
} elseif ( $numChanged > 0 ) {
$command = ord( fread($fp, 1) );
$status = ord( fread($fp, 1) );
$identifier = implode('', unpack("N", fread($fp, 4)));
if( $status > 0 ) {
// The socket has also been closed. Cause reopening in the loop outside.
$this->disconnect();
throw new MessageException("APNS responded with status $status: {$this->statusDesc[$status]} ($devicetoken).".microtime(), $status);
} else {
// unknown response, assume ok
}
} else {
// no response, assume ok
}
}