ios - 发送 voip 推送通知后是否应关闭与 APNs 的连接?

标签 ios swift apple-push-notifications

我正在使用 simplepush.php 脚本从用户向用户发送 voip 推送。 我的应用程序可能会发出许多此类推送请求,具体取决于它获得的用户数量。我发现的每个 simplepush.php 示例似乎都在最后明确关闭了连接 - 这是我的脚本(见最后一行):

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'voip.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client($apnsUrl, $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;

// Create the payload body
$body['aps'] = array(
    'alert' => $message,
    'sound' => 'default'
    );

$body['info'] = array(
  'roomname' => $roomName,
  'uuid' => $uuid
  );

// Encode the payload as JSON
$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));

if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);

请注意:我使用旧版 APNs 二进制接口(interface)发送通知而不是 HTTP/2 请求,因为所有 simplepush 脚本都使用它。我不太精通 PHP,但似乎脚本在每次调用结束时关闭连接:fclose($fp);

但根据 Apple 的说法,我应该保持连接打开:

Best Practices for Managing Connections Keep your connections with APNs open across multiple notifications; do not repeatedly open and close connections. APNs treats rapid connection and disconnection as a denial-of-service attack. https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW6

但由于我使用的是旧版二进制接口(interface),我真的应该在每次调用后关闭连接吗?还是我误解了这里的 fclose($fp); 函数?非常感谢任何关于使用此二进制文件时处理连接的适当方式的清晰说明!

最佳答案

解释

据我所知,不关闭每个通知的连接的建议来自批量通知传送领域,在该领域,许多用户会传送相同的通知。

除了可能被解释为攻击之外,一直关闭和重新打开是非常低效的,并且会导致巨大的交付延迟。只在流上写入二进制消息比打开和关闭每个通知要快得多。看这个例子:

// Open a connection to the apns server (this code is the same as a few lines below, so if changed here, also change there)
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', 'voip.pem');
stream_context_set_option($stream_context, 'ssl', 'passphrase', 'secret_pass');
$apns = stream_socket_client($url, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $stream_context);

// Return if connection is impossible
if (!$apns) { return; }

// Create payload body
$body['aps'] = array(
    'alert' => $title,
    'badge' => 1
);

// Encode the payload as json
$payload = json_encode($body);

// Iterate through token array
foreach($tokens as $token) {    
    $user_id = 2 // Random id ;)

    // Build binary notification
    $msg = pack("C", 1);
    $msg .= pack("N", $user_id);
    $msg .= pack("N", $notification_expiration_date);
    $msg .= pack("n", 32);
    $msg .= pack('H*', $token);
    $msg .= pack("n", strlen($payload));
    $msg .= $payload;

    // Send to the server
    $fwrite_result = fwrite($apns, $msg, strlen($msg));
}

fclose($apns);

看看它如何打开一个连接,为数组中的每个标记写入,然后关闭,而不是每次打开、写入和关闭。

以批量推送应用程序为例,现在由您的设计决定是否应保持连接。如果你每隔一小时发送一次通知,我认为打开和关闭每个通知是合适的。但是,如果您每分钟有多个通知的吞吐量,则需要保持连接打开。

建议

您可以采用的一种方法是在完成现有队列后查找要传送的任何新通知。如果没有,您可以再等几分钟,然后再次检查并关闭连接,如果仍然没有新内容,如果有,请保持打开状态并使用相同的连接发送新通知。

这符合 Apple 的建议:

You should leave a connection open unless you know it will be idle for an extended period of time—for example, if you only send notifications to your users once a day, it is acceptable practice to use a new connection each day.

警告

使用单个连接时要考虑的一件重要事情是错误处理:无效 token (生产/沙盒模式混淆)可能会导致连接在您不注意的情况下关闭,但还有其他帖子对此进行了进一步讨论。

关于ios - 发送 voip 推送通知后是否应关闭与 APNs 的连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49328316/

相关文章:

iOs 推送通知,不要收到请求授权的警报

ios - 使用 MPVolumeView,我的缩略图显示在使用 setVolumeThumbImage 的默认缩略图下方

ios - MKMapView 不读取给定的坐标

macos - 拖放 NSImage

swift - 为什么调用一个函数而不是传递一个带有一个参数的值有效,但更多的参数却不行?

ios - 使用 PushKit 有什么限制?

ios - iOS 应用程序图标上未显示角标(Badge)

ios - 编辑它的属性后将 nsobject 自定义类复制到数组

iphone - 在 iPhone 上模拟发送短信

ios - 如何在 SwiftUI 中以编程方式编辑 TextField 的边框颜色?