iOS 14 上的 UDP 监听器

tom*_*ank 2 udp network-programming bonjour swift ios14

我有一个关于如何在 iOS 14 上设置 UDP 侦听器的问题。我有一个 UDP 侦听器,该侦听器过去一直有效,但更新到 iOS 14 后,它偶尔有效/根本无效。

\n

它位于 NSObject 中,并在端口 15000(无特定 IP 地址)上侦听本地网络上的 UDP 广播。它使用 CocoaAsyncSocket 库。当我调用setUpSocket()本地网络权限时,不会触发,但应用程序能够偶尔拾取 UDP 数据包。

\n
\nvar socket: GCDAsyncUdpSocket?\nvar broadcastPort: UInt16 = 15000\nvar broadcastAddress: String = ""\nvar connectAddress = ""\nvar connectPort = 0\n\nfunc setUpSocket() {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0findUDP()\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0let socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0socket.setIPv4Enabled(true)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0socket.setIPv6Enabled(false)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0do {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0try socket.bind(toPort: broadcastPort) /*15000*/\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0try socket.enableBroadcast(false)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0try socket.beginReceiving()\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0} catch let error as NSError {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0print("Issue with setting up listener \\(error)")\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0}\n\n/*Called when UDP packets are received.*/\nfunc udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress: Data, withFilterContext filterContext: Any?) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0do {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0let jsonDictionary = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0if (connected == false) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0if (jsonDictionary["Addresses"] != nil) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0if (jsonDictionary["Addresses"] is NSArray) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0let addresses = jsonDictionary["Addresses"] as! NSArray\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0for i in addresses {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0let ipAddress:String = i as! String\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0if (ipAddress.range(of: "^([0-9]{1,3}\\\\.){3}[0-9]{1,3}(\\\\/([0-9]|[1-2][0-9]|3[0-2]))?$", options: .regularExpression) != nil) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0connectAddress = ipAddress\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0connectPort = jsonDictionary["Port"] as! Int\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n          /*Sets up a TCP connection on the IP and Port provided in the UDP broadcast.*/\n          setupNetworkCommunication(ip: connectAddress, port: connectPort)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0closeSocket()\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0} catch let error {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0return print(error)\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\xc2\xa0\xc2\xa0}\n\n
Run Code Online (Sandbox Code Playgroud)\n

我如何更新它以符合 iOS 14?如果我需要更新以使用 Bonjour 服务,如何在不指定地址的情况下监听端口(并且无需查找特定的 Bonjour 服务广播,因为我正在查找的广播不使用 Bonjour)。

\n

是否可以快速打开和关闭 Bonjour NWBrowser 以触发网络权限,然后按原样使用我的代码?这似乎有效,但充其量也显得很老套。

\n

提前致谢。

\n

小智 5

为了CocoaAsyncSocket在我们的应用程序中使用 UDP,我们必须执行以下步骤:

  1. 向Apple请求多播授权(请求者必须是团队的帐户持有者):com.apple.developer.networking.multicast

  2. 在目标的 中Info.plist,为以下键设置一个字符串:

    隐私 - 本地网络使用说明

  3. 从 Apple 获得权利许可后,为*.entitlements您的应用程序文件中的以下键添加 true(1) 布尔值(最后一步是阻止我们接收 UDP 广播数据包的原因):

    com.apple.developer.networking.multicast

    *.entitlements 文件示例