iOS组播的那些坑

作者: 片片碎 | 来源:发表于2019-11-29 17:55 被阅读0次

    一、组播那些坑

    1、发不出UDP数据包

    1.1、 原因一:未开启网络权限

    ios12后要开启网络权限才能把包发出去,不开启网络权限发不出udp包(不管是广播还是组播),提示如下

    no route to host
    

    解决方案:开启网络权限“Access WiFi Information”

    截屏2019-11-19下午3.03.18.png
    1.2、 原因一:TTL设置转发数不够

    GCDAsyncUdpSocket中默认TTL参数为1,TTL每转发一级就减1,减到0就不转发,手机发送到路由器一级,就减少到0了,路由器就不会转发出去了。

    解决方案:修改TTL的值

       __block typeof(self) bself = self;
         [clientUdpSocket performBlock:^{
             char ttl = 16;//默认为1
             int ret = 0;
             int socketFd = [bself->clientUdpSocket socketFD];
             ret = setsockopt(socketFd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
             if (ret != 0) {
                 [self->clientUdpSocket close];
                 self->clientUdpSocket = nil;
                 });
             }
         }];
    

    2、IP包加入组报错

    2.1、原因一:未绑定端口
    join multicastGroup failure error:Error Domain=GCDAsyncUdpSocketErrorDomain Code=1 "Must bind a socket before joining a multicast group." UserInfo={NSLocalizedDescription=Must bind a socket before joining a multicast group.
    

    解决方案:socket绑定端口号

    [clientUdpSocket bindToPort:0 error:&error]
    
    2.2、原因二:重复添加
    Error Domain=NSPOSIXErrorDomain Code=48 "Address already in use" 
    UserInfo={NSLocalizedDescription=Address already in use, 
    NSLocalizedFailureReason=Error in setsockopt() function}
    

    解决方案:不使用时需移除,这样才能保证下次添加不报错

    [clientUdpSocket leaveMulticastGroup:host error:&error];
    
    2.3、原因三:添加组播地址报如下错【偶现】
    join multicastGroup failure error:Error
    Domain=NSPOSIXErrorDomain Code=12 "Cannot allocate
    memory" UserInfo={NSLocalizedDescription=Cannot allocate
    memory, NSLocalizedFailureReason=Error in setsockopt() function} 
    

    解决方案\color{red}{偶现现象,暂时不知道原因,如有知道的请告知}

    3、关于SSID和BSSID的获取

    3.1、iOS13 获取不到SSID和BSSID

    解决方案

    • 开启定位
    • 开启网络权限“Access WiFi Information”
    3.2、定位权限开启不生效

    info.list添加了以下权限,但是还是未弹出授权Alter

    NSLocationAlwaysUsageDescription NSLocationWhenInUseUsageDescription
    

    应用设置中也没有定位选项,如下

    image.png
    解决方案
    你要获取权限self.locationManager requestWhenInUseAuthorization
    
    这个是在运行期间使用,另外一个是后台使用,你要用哪个就选择哪个
    
    你先判断你的定位是否可行,如果行就判断是什么情况,如没有权限就去申请,如果是用户拒绝了,就是跳转到设置
    
     
    
    -(void)clickToMapVC{
    
        
    
        //确定用户的位置服务是否启用,位置服务在设置中是否被禁用
    
        BOOL enable      =[CLLocationManager locationServicesEnabled];
    
        NSInteger status =[CLLocationManager authorizationStatus];
    
        if(  !enable || status< 2){
    
            //尚未授权位置权限
    
            if ([[UIDevice currentDevice].systemVersion floatValue] >= 8)
    
            {
    
                //系统位置授权弹窗
    
                _lManager =[[CLLocationManager alloc]init];
    
                [_lManager requestAlwaysAuthorization];
    
                [_lManager requestWhenInUseAuthorization];
    
                
    
                  [self initLocation];
    
            }
    
        }else{
    
            if (status == kCLAuthorizationStatusDenied) {
    
                //拒绝使用位置
    
               [Helper showSettingAlertStr:@"上传图片需要开启位置授权,请在iPhone的“设置->隐私->位置”中打开本应用的访问权限"];
    
            }else{
    
    //            //允许使用位置
    
                
    
                 [self initLocation];
    
     
    
            }
    
        
    
    }
    
        
    
    }
    
    

    4、收包端收到其他包

    4.1 收到其他数据包,判断不准问题

    解决方案:如下:

    截屏2019-11-29下午5.54.22.png

    二、补充知识点

    1、端口为0

    Port 0 is officially a reserved port in TCP/IP networking, meaning
    that it should not be used for any TCP or UDP network
    communications. However, port 0 sometimes takes on a special
    meaning in network programming, particularly Unix socket
    programming. In that environment, port 0 is a programming
    technique for specifying system-allocated (dynamic) ports.
    

    端口号 0 是一个预留的端口号,代表的意思就是它在TCP或者UDP网络传输中应该不会被用到。但是在网络编程中,尤其是在unix socket编程当中,它有一些特殊的含义。在unix socket编程当中,端口号 0 是一种由系统指定动态生成的端口。

    Description:

    Configuring a new socket connection requires assigning a TCP or
    UDP port number. Instead of hard-coding a particular port number,
    or writing code that searches for an available port on the local
    system, network programmers can instead specify port 0 as a
    connection parameter. That triggers the operating system to
    automatically search for and return the next available port in the
    dynamic port number range.Unix, Windows and other operating
    systems vary slightly in their handling of port 0.
    

    当建立新的TCP和UDP socket连接时,需要给它们指定端口号。 为了避免这种写死端口号的做法或者说为了从本地系统中找到可用端口。网络编程员们可以以端口号0来作为连接参数。这样的话操作系统就会从动态端口号范围内搜索接下来可以使用的端口号。windows系统和其他操作系统在处理端口号0时有一些细微的差别。

    2、关于TTL

    每当路由器转发组播数据包,IP包中的TTL(Time To Live)值都减1。若数据包的TTL减少到0,则路由器将抛弃该数据包。TTL阈值可用于组播路由器的各个接口,以防止在该接口上转发低于TTL阈值的组播数据包。这样可对组播的范围加以控制。下表给出典型的初始TTL值和作为不同TTL边界的路由器接口TTL阈值。

    范围 初始值 TTL阈值
    本地网 1 N/A
    区域 15 16
    地球 63 64
    全球 127 128

    3、关于IP

    组播地址使用的是D类地址,D类IP地址(224.0.0.0到239.255.255.255)不识别互联网内的单个接口,但识别接口组,被称为多播组。D类地址的的范围及含义如下表:

    | D类地址范围 | 含义 |
    | ------- | :-------- | :--- |
    | 224.0.0.0 ~ 224.0.0.255 | 预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其他地址供路由协议使用,路由器不做转发。 |
    | 224.0.1.0 ~ 224.0.1.255 | 公用组播地址,用户可用的组播地址(临时组地址),全网范围内有效|
    | 224.0.2.0 ~ 238.255.255.255 | 为用户可用的组播地址(临时组地址),全网范围内有效; |
    | 239.0.0.0 ~ 239.255.255.255 | 本地管理组播地址,仅在特定的本地范围有效 |

    更多关于IP地址的资料:IP地址划分、组播地址、公有IP、私有IP

    4、 组播IP和组播MAC

    首先IP地址是在网络层的,MAC地址(也成为物理地址或硬件地址),物理地址是数据链路层和物理层使用的地址。物理地址已经固化在网卡上,是不会变的,你电脑上的MAC地址是唯一的。
    在类似以太网的网络中,使用单播地址时,ARP通常根据目的地的IPv4地址确定其MAC地址,而在IPv6中则是由邻居发现协议(ND)来承担类似工作。在广播中,一个MAC地址可以用于达到一个LANVLAN上的所有站点。那么组播中应该如何确定何种MAC地址应该放置于链路层帧中呢?理想的情况下,我们不必使用协议报文来确定适当的MAC地址,而是简单地将一个IP组播地址直接映射到一些对应的MAC地址。这些网络代表了使用IP组播的最常见的网络类型,具体映射方法在IPv4和IPv6中略有不同

    4.1、IPv4组播MAC地址

    IANA规定,IPv4组播MAC地址的高24位为0x01005E,第25位为0,低23位为IPv4组播地址的低23位。IPv4组播地址与MAC地址的映射关系如下图所示。

    image.png

    由于IPv4组播地址的高4位是1110,代表组播标识,而低28位中只有23位被映射到IPv4组播MAC地址,这样IPv4组播地址中就有5位信息丢失。于是,就有32个IPv4组播地址映射到了同一个IPv4组播MAC地址上,因此在二层处理过程中,设备可能要接收一些本IPv4组播组以外的组播数据,而这些多余的组播数据就需要设备的上层进行过滤了。

    VRRP4的组播IP:224.0.0.18 组播Mac:0100-5e00-0012

    4.2、IPV6对应的MAC地址

    映射规则:组播MAC地址的前16位固定为0x3333,将组播IPV6地址的后32位直接映射到组播MAC地址的后32位就可以了。


    image.png

    如:IPV6地址为--FF12::1234:5678/64
    对应的组播MAC地址为--3333:1234:5678

    VRRP6的组播IP:FF02::12组播Mac:3333-0000-0012

    相关文章

      网友评论

        本文标题:iOS组播的那些坑

        本文链接:https://www.haomeiwen.com/subject/yqnwictx.html