iOS 14上的UDP侦听器

问题描述

我有一个关于如何在iOS 14上设置UDP侦听器的问题。我有一个曾经使用过的UDP侦听器,但是在更新到iOS 14之后,它偶尔会起作用/根本无法工作。

它驻留在NSObject中,并在端口15000(无特定IP地址)上侦听本地网络上的UDP广播。它使用CocoaAsyncSocket库。当我致电setUpSocket()时,不会触发本地网络权限,但是该应用程序可以偶尔接收UDP数据包。


var socket: GCDAsyncUdpSocket?
var broadcastPort: UInt16 = 15000
var broadcastAddress: String = ""
var connectAddress = ""
var connectPort = 0

func setUpSocket() {
    findUDP()
    let socket = GCDAsyncUdpSocket(delegate: self,delegateQueue: DispatchQueue.main)
     
    socket.setIPv4Enabled(true)
    socket.setIPv6Enabled(false)
     
    do {
      try socket.bind(toPort: broadcastPort) /*15000*/
      try socket.enableBroadcast(false)
      try socket.beginReceiving()
       
    } catch let error as NSError {
       
      print("Issue with setting up listener \(error)")
       
    }
     
  }

/*Called when UDP packets are received.*/
func udpSocket(_ sock: GCDAsyncUdpSocket,didReceive data: Data,fromAddress: Data,withFilterContext filterContext: Any?) {
     
    do {
      let jsonDictionary = try JSONSerialization.jsonObject(with: data,options: []) as! [String : Any]
       
      if (connected == false) {
        if (jsonDictionary["Addresses"] != nil) {
          if (jsonDictionary["Addresses"] is NSArray) {
            let addresses = jsonDictionary["Addresses"] as! NSArray
             
            for i in addresses {
              let ipAddress:String = i as! String
              if (ipAddress.range(of: "^([0-9]{1,3}\\.){3}[0-9]{1,3}(\\/([0-9]|[1-2][0-9]|3[0-2]))?$",options: .regularExpression) != nil) {
                connectAddress = ipAddress
              }
            }
            connectPort = jsonDictionary["Port"] as! Int
          }
           
          /*Sets up a TCP connection on the IP and Port provided in the UDP broadcast.*/
          setupNetworkCommunication(ip: connectAddress,port: connectPort)
          
          closeSocket()

        }
      }
       
    } catch let error {
      return print(error)
    }
  }

如何更新它以符合iOS 14?如果需要更新才能使用Bonjour服务,如何在不指定地址的情况下在端口上侦听(而不必查找特定的Bonjour服务广播,因为我要查找的广播不使用Bonjour)。 / p>

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

谢谢。

解决方法

我能够在Apple开发者论坛上进行更多探索,并获得一些帮助,并在此处为有兴趣的人发布答案。

我最终使用NWListener侦听UDP数据包,然后在收到某些信息后立即建立NWConnection。我使用此NWConnection从UDP广播中读取数据。

摘自奎因《爱斯基摩人》:

侦听通过NWListener进行的UDP广播,然后使用它出售的NWConnection对象(通过new connection handler)与广播的发送方进行单播通信,这是一个预期的用例。 / p>

我鼓励阅读此书的任何人也检出our discussion on the Apple Developer Forum

这是我的实现方式

  var udpListener: NWListener?
  var udpConnection: NWConnection?
  var backgroundQueueUdpListener  = DispatchQueue.main
   
  func findUDP() {
    let params = NWParameters.udp
    udpListener = try? NWListener(using: params,on: 15000)
     
    udpListener?.service = NWListener.Service.init(type: "_appname._udp")
     
    self.udpListener?.stateUpdateHandler = { update in
      print("update")
      print(update)
      switch update {
      case .failed:
        print("failed")
      default:
        print("default update")
      }
    }
    self.udpListener?.newConnectionHandler = { connection in
      print("connection")
      print(connection)
      self.createConnection(connection: connection)
      self.udpListener?.cancel()
    }
    udpListener?.start(queue: self.backgroundQueueUdpListener)
  }
   
  func createConnection(connection: NWConnection) {
    self.udpConnection = connection
      self.udpConnection?.stateUpdateHandler = { (newState) in
        switch (newState) {
        case .ready:
          print("ready")
          self.send()
          self.receive()
        case .setup:
          print("setup")
        case .cancelled:
          print("cancelled")
        case .preparing:
          print("Preparing")
        default:
          print("waiting or failed")
        }
      }
      self.udpConnection?.start(queue: .global())
  }
   
  func endConnection() {
    self.udpConnection?.cancel()
  }
,

要在我们的应用程序中将Info.plist与UDP配合使用,我们必须执行以下步骤:

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

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

    隐私-本地网络使用说明

  3. 在获得Apple的权利许可后,在您应用的com.apple.developer.networking.multicast文件中为以下密钥添加一个true(1)布尔值(这是阻止我们接收UDP广播的最后一步)数据包):

    add_filter('woocommerce_add_to_cart_validation','shalior_flag_already_added_products_as_invalid',10,2); function shalior_flag_already_added_products_as_invalid ($result,$product_id){ if (false === $result){ return $result; } $url = wc_get_cart_url(); foreach ( WC()->cart->get_cart() as $cart_item ) { $cart_item_product_id = $cart_item['product_id']; if($product_id === $cart_item['product_id'] ) { $result = false; } } if (false === $result){ add_filter('woocommerce_cart_redirect_after_error',function (){ return wc_get_cart_url(); },999 ); } return $result; }

    *.entitlements file example

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...