本文介绍了iOS 14 上的 UDP 侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于如何在 iOS 14 上设置 UDP 侦听器的问题.我有一个过去工作过的 UDP 侦听器,但在更新到 iOS 14 后,它偶尔工作/根本不工作.

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

var 套接字:GCDAsyncUdpSocket?var 广播端口:UInt16 = 15000var broadcastAddress: String = "";var connectAddress = "";变量连接端口 = 0func setUpSocket() {发现UDP()let socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)socket.setIPv4Enabled(true)socket.setIPv6Enabled(false)做 {试试 socket.bind(toPort: broadcastPort)/*15000*/尝试 socket.enableBroadcast(false)尝试 socket.beginReceiving()} catch let error as NSError {打印(设置监听器的问题\(错误)")}}/*当收到UDP数据包时调用.*/func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress: Data, withFilterContext filterContext: Any?) {做 {让 jsonDictionary = 尝试 JSONSerialization.jsonObject(with: data, options: []) as![字符串:任意]如果(连接 == 假){如果(jsonDictionary[地址"] != nil){如果(jsonDictionary[地址"] 是 NSArray){让地址 = jsonDictionary[地址"] 作为!数组对于地址中的 i {让 ipAddress:String = i as!细绳if (ipAddress.range(of: "^([0-9]{1,3}\\.){3}[0-9]{1,3}(\\/([0-9]|[1-2][0-9]|3[0-2]))?$",选项:.regularExpression) != nil) {连接地址 = ipAddress}}connectPort = jsonDictionary[Port"] as!整数}/*在UDP广播中提供的IP和端口上建立TCP连接.*/设置网络通信(ip:connectAddress,端口:connectPort)关闭套接字()}}} 抓住让错误{返回打印(错误)}}

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

快速打开和关闭 Bonjour NWBrowser 以触发网络权限,然后按原样使用我的代码是否可以接受?这似乎有效,但充其量似乎很糟糕.

提前致谢.

解决方案

我能够对此进行更多探索,并通过 Apple 开发者论坛获得了一些帮助,并在此处为感兴趣的人发布了答案.

我最终使用了一个 NWListener 来监听 UDP 数据包,然后在我收到一些东西后设置一个 NWConnection.我使用这个 NWConnection 从 UDP 广播中读取数据.

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

通过 NWListener 侦听 UDP 广播,然后使用它提供的 NWConnection 对象(通过 新的连接处理程序) 与广播的发送方通过单播进行通信是预期的用例.

我鼓励任何阅读本文的人查看我们在 Apple 开发者论坛上的讨论 也是.

这是我的实现:

 var udpListener: NWListener?var udpConnection:NWConnection?var backgroundQueueUdpListener = DispatchQueue.mainfunc findUDP() {让参数 = NWParameters.udpudpListener = 试试?NWListener(使用:params,在:15000)udpListener?.service = NWListener.Service.init(类型:_appname._udp")self.udpListener?.stateUpdateHandler = { 更新打印(更新")打印(更新)切换更新{案例.失败:打印(失败")默认:打印(默认更新")}}self.udpListener?.newConnectionHandler = { 连接输入打印(连接")打印(连接)self.createConnection(连接:连接)self.udpListener?.cancel()}udpListener?.start(队列:self.backgroundQueueUdpListener)}func createConnection(连接:NWConnection){self.udpConnection = 连接self.udpConnection?.stateUpdateHandler = { (newState) in开关(新状态){案例 .ready:打印(准备好")self.send()self.receive()案例.setup:打印(设置")案例.取消:打印(取消")案例.准备:打印(准备中")默认:打印(等待或失败")}}self.udpConnection?.start(队列:.global())}功能结束连接(){self.udpConnection?.cancel()}

I have a question regarding how to set up a UDP listener on iOS 14. I have a UDP listener which has worked in the past, but after updating to iOS 14 it works sporadically/not at all.

This lives in an NSObject, and listens for a UDP broadcast across the local network on port 15000 (no specific IP address). It uses the CocoaAsyncSocket library. When I call setUpSocket() local network permissions are not triggered, but the app is able to sporadically pick up UDP packets.


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)
    }
  }

How can I update this to comply with iOS 14? If I need to update to use Bonjour services, how can I listen on a port without specifying an address (and without having to look for a specific Bonjour service broadcast, because the broadcast I'm looking for doesn't use Bonjour).

Is it acceptable to quickly open and close a Bonjour NWBrowser in order to trigger the network permissions, and then use my code as-is? This seems to work but seems hacky at best.

Thanks in advance.

解决方案

I was able to explore this some more and got some help via the apple developer forums, posting an answer here as well for those who are interested.

I ended up using an NWListener to listen for UDP packets, then set up an NWConnection once once I'd received something. I use this NWConnection to read data from the UDP broadcast.

From Quinn "The Eskimo:"

I encourage anyone reading this to check out our discussion on the Apple Developer Forum as well.

Here is my implementation:

  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()
  }

这篇关于iOS 14 上的 UDP 侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 04:14
查看更多