一、組播那些坑
1、發不出UDP數據包
1.1、 原因一:未開啟網絡權限
ios12后要開啟網絡權限才能把包發出去,不開啟網絡權限發不出udp包(不管是廣播還是組播),提示如下
no route to host
解決方案:開啟網絡權限“Access WiFi Information”
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}
解決方案:
3、關于SSID和BSSID的獲取
3.1、iOS13 獲取不到SSID和BSSID
解決方案:
- 開啟定位
- 開啟網絡權限“Access WiFi Information”
3.2、定位權限開啟不生效
info.list添加了以下權限,但是還是未彈出授權Alter
NSLocationAlwaysUsageDescription NSLocationWhenInUseUsageDescription
應用設置中也沒有定位選項,如下
解決方案:
你要獲取權限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 收到其他數據包,判斷不準問題
解決方案:如下:
二、補充知識點
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地址可以用于達到一個LAN或VLAN上的所有站點。那么組播中應該如何確定何種MAC地址應該放置于鏈路層幀中呢?理想的情況下,我們不必使用協議報文來確定適當的MAC地址,而是簡單地將一個IP組播地址直接映射到一些對應的MAC地址。這些網絡代表了使用IP組播的最常見的網絡類型,具體映射方法在IPv4和IPv6中略有不同
4.1、IPv4組播MAC地址
IANA規定,IPv4組播MAC地址的高24位為0x01005E,第25位為0,低23位為IPv4組播地址的低23位。IPv4組播地址與MAC地址的映射關系如下圖所示。
由于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位就可以了。
如:IPV6地址為--FF12::1234:5678/64
對應的組播MAC地址為--3333:1234:5678
VRRP6的組播IP:FF02::12組播Mac:3333-0000-0012