一蚁滋,前言
小編在目前在做智能硬件方面的項(xiàng)目,遇到一個(gè)需求赘淮,就是開啟手機(jī)熱點(diǎn)辕录,然后將智能設(shè)備配網(wǎng)連接到手機(jī)上,手機(jī)發(fā)送UDP廣播查找設(shè)備梢卸。
二走诞,問題
手機(jī)通過 255.255.255.255 地址進(jìn)行UDP廣播,設(shè)備沒有收到消息蛤高,連接同一個(gè)熱點(diǎn)的設(shè)備通過是能收到廣播消息的蚣旱,并且能相互通信。
三襟齿,個(gè)人分析
手機(jī)是連接著4G網(wǎng)絡(luò)姻锁,并且開啟熱點(diǎn),如果直接通過 255.255.255.255 地址進(jìn)行廣播的話猜欺,它怎么知道該廣播到外網(wǎng)去呢還是手機(jī)熱點(diǎn)的網(wǎng)段位隶,因此猜測(cè)應(yīng)該對(duì)指定的網(wǎng)段進(jìn)行廣播.
四,通過局域網(wǎng) IP 計(jì)算網(wǎng)絡(luò)廣播地址
網(wǎng)段IP = 子網(wǎng)掩碼&IP
網(wǎng)段最大地址 = ~(子網(wǎng)掩碼)
廣播地址 = 網(wǎng)段地址 + 網(wǎng)段最大地址;
例如:
IP:172.20.10.10/28
子網(wǎng)掩碼:255.255.255.240
子網(wǎng)掩碼二進(jìn)制:11111111 11111111 11111111 11110000
網(wǎng)段IP = 172.20.10.10 & 255.255.255.240 (按位與) = 172.20.10.0
網(wǎng)段最大地址 = ~(255.255.255.240 ) = 15
廣播地址 = 172.20.10.0 + 15 = 172.20.10.15
也可以使用在線工具計(jì)算 http://ip.chacuo.net/ipcalc
其他的網(wǎng)絡(luò)知識(shí)請(qǐng)百度 "子網(wǎng)掩碼","IP","廣播地址","局域網(wǎng)廣域網(wǎng)","IP地址分類" ,"IP地址分類主機(jī)數(shù)量"等關(guān)鍵字
五开皿,實(shí)踐看看是否是這樣
1.首先我們?cè)?G網(wǎng)絡(luò)環(huán)境下開啟熱點(diǎn)
2.使用另一臺(tái)設(shè)備連接該熱點(diǎn)涧黄,并查看該熱點(diǎn)的詳細(xì)信息
可以拿到設(shè)備的ip(172.20.10.10) 子網(wǎng)掩碼(255.255.255.240)
通過第四點(diǎn)可以計(jì)算出子 廣播地址為172.20.10.15
然后在手機(jī)上或電腦上安裝一些網(wǎng)絡(luò)調(diào)試助手調(diào)試UDP
軟件推薦:
MAC:PacketSender
iOS:TCP/UDP
Android:網(wǎng)絡(luò)測(cè)試
Windows:網(wǎng)絡(luò)調(diào)試助手
小編拿iPhone 和 Android 機(jī)進(jìn)行測(cè)試,iPhone開啟熱點(diǎn)赋荆,Android模擬設(shè)備笋妥。
iPhone
Android
可以發(fā)現(xiàn)開啟熱點(diǎn)的手機(jī)是可以見數(shù)據(jù)廣播到局域網(wǎng)中的。
六窄潭,iOS 相關(guān)代碼
獲取熱點(diǎn)手機(jī)在局域網(wǎng)中的IP地址
UIDevice+GBCategory.h
#import <UIKit/UIKit.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
//#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
@interface UIDevice(GBCategory)
- (NSDictionary *)getIPAddresses;
- (NSString *)getIPAddress:(BOOL)preferIPv4;
/**
獲取熱點(diǎn)地址
@param preferIPv4 <#preferIPv4 description#>
@return <#return value description#>
*/
- (NSString *)getHotSpotIp;
/**
獲取熱點(diǎn)子網(wǎng)掩碼
@param preferIPv4 <#preferIPv4 description#>
@return <#return value description#>
*/
- (NSString *)getHotSpotMask;
/**
獲取熱點(diǎn)網(wǎng)絡(luò)廣播地址
@return <#return value description#>
*/
- (NSString *)getHotSpotBroadcastIp;
- (BOOL)flagWithOpenHotSpot;
@end
UIDevice+GBCategory.m
#import "UIDevice+GBCategory.h"
#import <UIDevice+YYAdd.h>
@implementation UIDevice(GBCategory)
- (NSDictionary *)getIPAddresses
{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
const struct sockaddr_in *netmask = (const struct sockaddr_in*)interface->ifa_netmask;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
if (netmask) {
NSString *sin_addr = [NSString stringWithUTF8String:inet_ntoa(addr->sin_addr)];
NSString *ifa_netmask = [NSString stringWithUTF8String:inet_ntoa(netmask->sin_addr)];
NSString *key = [NSString stringWithFormat:@"ifa_netmask/%@", type];
addresses[key] = ifa_netmask;
NSLog(@"ip Info sin_addr:%@ - %@",sin_addr,ifa_netmask);
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
- (NSString *)getIPAddress:(BOOL)preferIPv4
{
NSArray *searchArray = preferIPv4 ?
@[ /*IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6,*/ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
@[ /*IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4,*/ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
NSDictionary *addresses = [self getIPAddresses];
NSLog(@"addresses: %@", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : @"0.0.0.0";
}
- (NSString *)getHotSpotIp{
NSDictionary *dict = [self getIPAddresses];
if ( dict ) {
NSArray *keys = dict.allKeys;
for ( NSString *key in keys) {
if ( key && [key containsString:@"bridge"] && [key containsString:@"ipv4"])
return dict[key];
}
}
return @"0.0.0.0";
}
- (NSString *)getHotSpotMask{
NSDictionary *dict = [self getIPAddresses];
if ( dict ) {
NSArray *keys = dict.allKeys;
for ( NSString *key in keys) {
if ( key && [key containsString:@"ifa_netmask"] && [key containsString:@"ipv4"])
return dict[key];
}
}
return @"0.0.0.0";
}
- (NSString *)getHotSpotBroadcastIp{
NSString *ip = [self getHotSpotIp];
NSString *mask = [self getHotSpotMask];
NSArray *ips = [ip componentsSeparatedByString:@"."];
NSArray *masks = [mask componentsSeparatedByString:@"."];
NSMutableString *b_address = [[NSMutableString alloc] init]; //網(wǎng)段地址
for (int index = 0; index < 4; index ++) {
unsigned char value = [ips[index] unsignedCharValue] & [masks[index] unsignedCharValue];
if (index!=3) {
[b_address appendFormat:@"%d.",value];
}else{
unsigned char v = (~[masks[index] unsignedCharValue]) + value;
[b_address appendFormat:@"%d",v];
}
}
return b_address;
}
- (BOOL)flagWithOpenHotSpot
{
NSDictionary *dict = [self getIPAddresses];
if ( dict ) {
NSArray *keys = dict.allKeys;
for ( NSString *key in keys) {
if ( key && [key containsString:@"bridge"])
return YES;
}
}
return NO;
}
@end
獲取熱點(diǎn)名稱
NSString *hotpotName = [[UIDevice currentDevice] name];