iOS 14 UDP收不到广播处理

iOS 14 UDP收不到广播处理

1. 简单说明

项目使用到了CocoaAsyncSocket,建立TCP之前,使用了UDP广播获取IP地址,但是系统升级到iOS 14之后,发现有台iPad间歇性可以收到广播,iPhone一直没有收到广播。

2. 解决办法

  1. Info.plist添加NSLocalNetworkUsageDescription

  2. 发送一次UDP广播,触发权限弹框,让用户点击好,允许访问本地网络。

    - (void)setupUdpSocket {
       NSError *error = nil;
       GCDAsyncUdpSocket *socket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
       self.udpSocket = socket;
       [socket setIPv4Enabled:YES];
       [socket setIPv6Enabled:NO];
       [socket bindToPort:udpPort error:&error];
    
       // 关键一行代码,发送广播,即使应用不需要。如果不发送,无法触发是否允许访问本地网络弹框。
       [self.udpSocket sendData:[@{} mj_JSONData] toHost:@"255.255.255.255" port:udpPort withTimeout:10 tag:100];
    
       [socket enableBroadcast:YES error:&error];
       [socket beginReceiving:&error];
    }
    

  3. 如果上面两步不生效,或则在正式版本不生效,继续往下看。

  4. 到这个页面申请APP接受组播或广播的权限Multicast Networking Entitlement Request

    如果打开报502,可以尝试复制链接到Safari打开重试。

    打开后页面会有下面说明,主要是填写App信息并解释一下用到UDP组播或广播的目的。

    // 说明
    Multicast Networking Entitlement Request
    
    This entitlement allows advanced networking apps to interact with their local network by sending multicast and broadcast IP packets and browsing for arbitrary Bonjour service types. Your app may need to access this level of networking in order to communicate with custom or non-standard devices or to act as a network utility. If your app needs this entitlement to function properly on iOS 14 or later, provide the following information.
    
    // 开发账号信息
    Developer Information
    
    // App 信息 
    App Information
    ......
    Explain why your app needs to send multicast or broadcast traffic, or browse for all Bonjour service types.
    

  5. 如果你的APP需要发送UDP广播,需要先发送一个伪包来触发弹框(本地网络访问),让用户确定后,再开始发送UDP广播。如果只是接受广播,不用处理。

  6. 填写完点击发送。

    Thank you for your submission.
    We will review your request and will get back to you.
    
  7. 之后Apple通过邮件回复

    // 官方回复要求我再描述的详细一点,其实我描述的已经很清楚了,但是用的是中文,所以还是乖乖用英文具体描述一下吧。 主要用来获取IP地址,端口号已经协商好了。
    
    Hello,
    
    Thank you for your interest in Multicast Networking. Can you please provide more details on which multicast or broadcast protocol (IP address and port) you need to use? What messages are exchanged between devices?
    Specifically, it seems as though this type of device discovery could be accomplished via Bonjour, which doesn’t need the entitlement.
    
    Best regards,
    Apple Networking
    
  8. 最后通过后,Apple回复已通过,参考Instructions for using the entitlement (使用New Process)配置即可。

    主要配置流程为:

    • 登录开发者网站
    • Certificates, Identifiers & Profiles, 选择 Identifiers
    • 选择你想设置的应用Id
    • 滑动到最后Additional Capabilities --> Multicast Networking 勾选后保存
    • 接下来的全部可以省略(下文解释)

    链接给出的新方案,需要把Xcode的 “Automatically manage signing”改为手动,自己去配置证书,而且还要添加.entitlements文件,添加com.apple.developer.networking.multicast设置为bool类型,值为true,后面还说明了真机编译,然后使用终端验证App和Profile该权限可用。

    注意注意注意:这些配置了都没有用,关键是要本地代码发送一次UDP广播,触发权限弹框,让用户点击好,允许访问本地网络。

    Hello, 
    
    Your request to use Multicast Networking was approved. You can now add the Multicast Networking entitlement with your Provisioning Profile.
    
    Instructions for using the entitlement are available and, for more information on using multicast, please read How to use multicast networking in your app. If you have questions or issues, please use the “Network” tag on the Apple Developer Forums.
    
    Best regards,
    Apple Networking
    

3. 参考原文内容

First things first, make sure you populate NSLocalNetworkUsageDescription in your Info.plist.

Next, make sure to apply for and, once it’s granted, enable the com.apple.developer.networking.multicast. iOS 14 will eventually require this for anyone doing multicasts and broadcasts (currently this requirement is not enforced for BSD Sockets clients).

Finally, be aware that the local network privacy alert is only triggered when you send traffic, so if your UDP socket only receives and never sends then you won’t see the alert. The current workaround is to send a dummy packet to trigger the alert.

看下官方说明

// A Boolean value that indicates whether an app can send or receive IP multicast traffic.
com.apple.developer.networking.multicast

/* Discussion
Your app must have this entitlement to send or receive IP multicast or broadcast on iOS. It also allows your app to browse and advertise arbitrary Bonjour service types.

This entitlement requires permission from Apple before you can use it in your app. Request permission from the Multicast Networking Entitlement Request page.
*/

4. 参考链接

https://developer.apple.com/forums/thread/662082

https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_networking_multicast

Instructions for using the entitlement

How to use multicast networking in your app

https://developer.apple.com/forums/thread/663591?answerId=640483022#640483022

https://developer.apple.com/forums/thread/663591?answerId=640483022#640483022连接中其中一位技术人员的回复,起到了关键作用,内容如下:

Unlike the OP's, my app is receiving UDP multicast, but not transmitting anything either. To make it work in iPadOS 14.0.1 I requested the multicast special entitlement and performed the steps according to Quinn's excellent instructions. However, there was no prompt for the user to allow the Local network access, and the app did not receive the UDP multicast. Only after adding a call to open an UDP socket and send data from iPad there was the prompt asking for Local network access. After giving access, the app started receiving UDP multicast. If the permission is then switched off via Settings/Privacy/Local Network, the UDP multicast is no longer received.

Since granting access by the user seems to be a requirement, in my opinion iPadOS should prompt for local network access even when the user is just binding to an UDP port to receive data. 

I am using GCDAsyncUdpSocket from [CocoaAsyncSocket](https://github.com/robbiehanson/CocoaAsyncSocket).
原文地址:https://www.cnblogs.com/chao8888/p/13749383.html