【问题标题】:What happens if the `NEPacketTunnelflow` method `readPacketsWithCompletionHandler` is called multiple times?如果多次调用 `NEPacketTunnelflow` 方法 `readPacket WithCompletionHandler` 会发生什么?
【发布时间】:2021-07-13 12:38:28
【问题描述】:

调用方法时

- (void)readPacketsWithCompletionHandler:(void (^)(
    NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols))completionHandler;

completionHandler 要么被直接调用,以防调用时数据包可用,要么在稍后数据包可用时调用。

然而没有记录的是:如果我在之前的集合 completionHandler 被调用之前再次调用此方法会发生什么?

新的处理程序是否会替换之前的 set 并且之前的 set 将不再被调用?

是否在数据到达时调度和调用处理程序?如果是这样,它们会按照我传递它们的顺序、相反的顺序还是随机顺序被调用?

有没有人对如何实现该方法有任何见解?

当然,我可以制作一个演示项目,创建一个测试设置,然后看看我通过测试得到了什么结果,但这非常耗时且不一定可靠。未指定行为的问题在于它可能会在不让任何人知道的情况下随意更改。此方法在 macOS 和 iOS 上的行为可能会有所不同,它可能会随着每个新的 OS 版本或一周中的哪一天而有所不同。

或者说没有记录是故意的?我是否必须将其解释为:您可以调用此方法一次,在执行回调后,您可以使用相同或新的回调再次调用它。其他一切都是未定义的行为,如果以不同的方式使用该 API,您不能也不应该依赖任何特定行为。

【问题讨论】:

    标签: ios objective-c macos networkextension


    【解决方案1】:

    由于到目前为止没有人回复,我尽力自己弄清楚。由于测试对我来说不够好,这就是我所做的:

    首先我使用this utility从macOS Big Sur的dyld缓存中提取了NetworkExtension框架二进制文件。

    然后我在生成的二进制文件上运行 otool -Vt 以获得二进制文件的反汇编转储。

    我的组装技能有点生疏,但据我所知,completionHandler 存储在名为packetHandler 的属性中,替换了之前存储的任何值。在该方法中还会创建一个回调,并将其存储在通过调用方法interface 获得的对象上。

    查看这个创建回调的代码时,它获取packetHandler属性的值,并在获取值后将其设置为NULL。然后它创建NSDataNSNumber 对象,将它们添加到NSArray 对象并使用这些数组调用获得的处理程序。

    所以似乎再次调用该方法只是替换了以前的completionHandler,在这种情况下永远不会被调用。因此,如果存在您的代码可能会替换它的可能性,那么如果隧道没有被拆除,您就不能依赖于最终会在将来的某个时间调用调度的处理程序。多次调用该方法来安排多个回调也没有效果,因为只有最后一个会被保留并最终被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 2016-01-23
      • 1970-01-01
      相关资源
      最近更新 更多