最近在搞網路相關的SDK,將自己在專案中能夠開放出來的,記錄下來,其中很多用到了C,相當於一個工具。後期還會選擇開放一些ping網路的工具,找鏈路節點的工具,最近就在搞這個。
歡迎大家關注我的公眾號,我會定期分享一些我在專案中遇到問題的解決辦法和一些iOS實用的技巧,現階段主要是整理出一些基礎的知識記錄下來
文章也會同步更新到我的部落格:
ppsheep.com
獲取當前裝置的IP地址
對於公網的IP當然,在我們本地裝置上是不能夠獲取到的,至少我沒有找到方法獲取到出口IP地址,但是區域網的IP還是能夠獲取到的,這裡ipv4和ipv6 都能夠獲取出來
+ (NSString *)deviceIPAdress
{
NSString *address = @"";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
success = getifaddrs(&interfaces);
if (success == 0) { // 0 表示獲取成功
temp_addr = interfaces;
while (temp_addr != NULL) {
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"] || [[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"pdp_ip0"])
{
//如果是IPV4地址,直接轉化
if (temp_addr->ifa_addr->sa_family == AF_INET){
// Get NSString from C String
address = [self formatIPV4Address:((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr];
}
//如果是IPV6地址
else if (temp_addr->ifa_addr->sa_family == AF_INET6){
address = [self formatIPV6Address:((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr];
if (address && ![address isEqualToString:@""] && ![address.uppercaseString hasPrefix:@"FE80"]) break;
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
//以FE80開始的地址是單播地址
if (address && ![address isEqualToString:@""] && ![address.uppercaseString hasPrefix:@"FE80"]) {
return address;
} else {
return @"127.0.0.1";
}
}複製程式碼
獲取當前裝置閘道器地址
閘道器地址,通俗點 就是路由器的地址,也是相對於區域網 這裡需要區分一下ipv4和ipv6,兩種獲取閘道器地址的方法是不一樣
//ipv4閘道器地址
+ (NSString *)getGatewayIPV4Address
{
NSString *address = nil;
/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY};
size_t l;
char *buf, *p;
struct rt_msghdr *rt;
struct sockaddr *sa;
struct sockaddr *sa_tab[RTAX_MAX];
int i;
if (sysctl(mib, sizeof(mib) / sizeof(int), 0, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}
if (l > 0) {
buf = malloc(l);
if (sysctl(mib, sizeof(mib) / sizeof(int), buf, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}
for (p = buf; p < buf + l; p += rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr *)(rt + 1);
for (i = 0; i < RTAX_MAX; i++) {
if (rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
} else {
sa_tab[i] = NULL;
}
}
if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) == (RTA_DST | RTA_GATEWAY)) &&
sa_tab[RTAX_DST]->sa_family == AF_INET &&
sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
unsigned char octet[4] = {0, 0, 0, 0};
int i;
for (i = 0; i < 4; i++) {
octet[i] = (((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr >>
(i * 8)) &
0xFF;
}
if (((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
in_addr_t addr =
((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
address = [self formatIPV4Address:*((struct in_addr *)&addr)];
// NSLog(@"IPV4address%@", address);
break;
}
}
}
free(buf);
}
return address;
}複製程式碼
//ipv6閘道器地址
+ (NSString *)getGatewayIPV6Address
{
NSString *address = nil;
/* net.route.0.inet.flags.gateway */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_FLAGS, RTF_GATEWAY};
size_t l;
char *buf, *p;
struct rt_msghdr *rt;
struct sockaddr_in6 *sa;
struct sockaddr_in6 *sa_tab[RTAX_MAX];
int i;
if (sysctl(mib, sizeof(mib) / sizeof(int), 0, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}
if (l > 0) {
buf = malloc(l);
if (sysctl(mib, sizeof(mib) / sizeof(int), buf, &l, 0, 0) < 0) {
address = @"192.168.0.1";
}
for (p = buf; p < buf + l; p += rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr_in6 *)(rt + 1);
for (i = 0; i < RTAX_MAX; i++) {
if (rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr_in6 *)((char *)sa + sa->sin6_len);
} else {
sa_tab[i] = NULL;
}
}
if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
&& sa_tab[RTAX_DST]->sin6_family == AF_INET6
&& sa_tab[RTAX_GATEWAY]->sin6_family == AF_INET6)
{
address = [self formatIPV6Address:((struct sockaddr_in6 *)(sa_tab[RTAX_GATEWAY]))->sin6_addr];
// NSLog(@"IPV6address%@", address);
break;
}
}
free(buf);
}
return address;
}複製程式碼
我們在獲取的時候判斷一下
/*!
* 獲取當前裝置閘道器地址
*/
+ (NSString *)getGatewayIPAddress{
NSString *address = nil;
NSString *gatewayIPV4 = [self getGatewayIPV4Address];
NSString *gatewayIPV6 = [self getGatewayIPV6Address];
if (gatewayIPV6 != nil) {
address = gatewayIPV6;
} else {
address = gatewayIPV4;
}
return address;
}複製程式碼
通過域名拿到域名對應的IP地址(CDN)
通過域名拿到的IP地址,一般來說,如果買了CDN的話,拿到的Ip都會是多個IP
/*!
* 通過hostname獲取ip列表 DNS解析地址
*/
+ (NSArray *)getDNSsWithDormain:(NSString *)hostName{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSArray *IPDNSs = [self getDNSWithHostName:hostName];
if (IPDNSs && IPDNSs.count > 0) {
[result addObjectsFromArray:IPDNSs];
}
return [NSArray arrayWithArray:result];
}
+ (NSArray *)getDNSWithHostName:(NSString *)hostName
{
const char *hostN = [hostName UTF8String];
Boolean result = false;
Boolean bResolved = false;
CFHostRef hostRef;
CFArrayRef addresses = NULL;
CFStringRef hostNameRef = CFStringCreateWithCString(kCFAllocatorDefault, hostN, kCFStringEncodingASCII);
hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostNameRef);
if (hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL);
if (result == true) {
addresses = CFHostGetAddressing(hostRef, &result);
}
}
bResolved = result;
NSMutableArray *ipAddresses = [NSMutableArray array];
if(bResolved)
{
struct sockaddr_in* remoteAddr;
for(int i = 0; i < CFArrayGetCount(addresses); i++)
{
CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, i);
remoteAddr = (struct sockaddr_in*)CFDataGetBytePtr(saData);
if(remoteAddr != NULL)
{
//獲取IP地址
const char *strIP41 = inet_ntoa(remoteAddr->sin_addr);
NSString *strDNS =[NSString stringWithCString:strIP41 encoding:NSASCIIStringEncoding];
[ipAddresses addObject:strDNS];
}
}
}
CFRelease(hostNameRef);
if (hostRef) {
CFRelease(hostRef);
}
return [NSArray arrayWithArray:ipAddresses];
}複製程式碼
獲取當前的網路狀況
如果是WIFI環境,直接返回wifi 如果是蜂窩網路環境,那麼還可以區分到底是那個運營商,還可以區分是使用的什麼網路,4G 3G 2G等 運營商暫時區分了國內的三大運營商,如果還需要區分國外的,可以維基百科上查對應的code
+(NSString *)currentNetInfo{
NSString *returnName = nil;
PPSNetWorkType type = [PPSGetAppEnvironment getNetworkTypeFromStatusBar];
if (type == PPSNetWorkTypeWiFi) {
returnName = @"WIFI";
return returnName;
}
NSString *carrierName = nil;
CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netInfo subscriberCellularProvider];
if (carrier != NULL) {
NSArray *chinaMobileMics = @[@"0",@"2",@"7"];//移動code
NSArray *chinaTelecomMics = @[@"3",@"5",@"11"];//電信code
NSArray *chinaUnicomMics = @[@"1",@"6"];//聯通code
NSString *mobileNetworkCode = [carrier mobileNetworkCode];
if ([chinaMobileMics containsObject:mobileNetworkCode]) {
carrierName = @"chinamobile";
}else if ([chinaTelecomMics containsObject:mobileNetworkCode]){
carrierName = @"chinatelecom";
}else if ([chinaUnicomMics containsObject:mobileNetworkCode]){
carrierName = @"chinaunicom";
}else{
carrierName = @"unknown";
}
} else {
carrierName = @"unknown";
}
switch (type) {
case PPSNetWorkType2G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"2G"];
break;
case PPSNetWorkType3G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"3G"];
break;
case PPSNetWorkType4G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"4G"];
break;
case PPSNetWorkType5G:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"5G"];
break;
case PPSNetWorkTypeNone:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"unknown"];
break;
default:
returnName = [NSString stringWithFormat:@"%@_%@",carrierName,@"unknown"];
break;
}
return returnName;
}複製程式碼
獲取當前的裝置資訊
獲取當前裝置的資訊,是iPhone 4 5 6 7還是 等等 還有系統的版本號 手機、平板
之類的都能夠去區分出來
/**
獲取裝置的型別
@return 裝置型別
*/
+ (NSString *)deviceInfo {
struct utsname systemInfo;
uname(&systemInfo);
NSString* code = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
static NSDictionary* deviceNamesByCode = nil;
if (!deviceNamesByCode) {
deviceNamesByCode = @{@"i386" :@"Simulator",
@"x86_64" :@"Simulator",
@"iPod1,1" :@"iPod Touch", // (Original)
@"iPod2,1" :@"iPod Touch", // (Second Generation)
@"iPod3,1" :@"iPod Touch", // (Third Generation)
@"iPod4,1" :@"iPod Touch", // (Fourth Generation)
@"iPod7,1" :@"iPod Touch", // (6th Generation)
@"iPhone1,1" :@"iPhone", // (Original)
@"iPhone1,2" :@"iPhone", // (3G)
@"iPhone2,1" :@"iPhone", // (3GS)
@"iPad1,1" :@"iPad", // (Original)
@"iPad2,1" :@"iPad 2", //
@"iPad3,1" :@"iPad", // (3rd Generation)
@"iPhone3,1" :@"iPhone 4", // (GSM)
@"iPhone3,3" :@"iPhone 4", // (CDMA/Verizon/Sprint)
@"iPhone4,1" :@"iPhone 4S", //
@"iPhone5,1" :@"iPhone 5", // (model A1428, AT&T/Canada)
@"iPhone5,2" :@"iPhone 5", // (model A1429, everything else)
@"iPad3,4" :@"iPad", // (4th Generation)
@"iPad2,5" :@"iPad Mini", // (Original)
@"iPhone5,3" :@"iPhone 5c", // (model A1456, A1532 | GSM)
@"iPhone5,4" :@"iPhone 5c", // (model A1507, A1516, A1526 (China), A1529 | Global)
@"iPhone6,1" :@"iPhone 5s", // (model A1433, A1533 | GSM)
@"iPhone6,2" :@"iPhone 5s", // (model A1457, A1518, A1528 (China), A1530 | Global)
@"iPhone7,1" :@"iPhone 6 Plus", //
@"iPhone7,2" :@"iPhone 6", //
@"iPhone8,1" :@"iPhone 6S", //
@"iPhone8,2" :@"iPhone 6S Plus", //
@"iPhone8,4" :@"iPhone SE", //
@"iPhone9,1" :@"iPhone 7", //
@"iPhone9,3" :@"iPhone 7", //
@"iPhone9,2" :@"iPhone 7 Plus", //
@"iPhone9,4" :@"iPhone 7 Plus", //
@"iPad4,1" :@"iPad Air", // 5th Generation iPad (iPad Air) - Wifi
@"iPad4,2" :@"iPad Air", // 5th Generation iPad (iPad Air) - Cellular
@"iPad4,4" :@"iPad Mini", // (2nd Generation iPad Mini - Wifi)
@"iPad4,5" :@"iPad Mini", // (2nd Generation iPad Mini - Cellular)
@"iPad4,7" :@"iPad Mini", // (3rd Generation iPad Mini - Wifi (model A1599))
@"iPad6,7" :@"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1584)
@"iPad6,8" :@"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1652)
@"iPad6,3" :@"iPad Pro (9.7\")", // iPad Pro 9.7 inches - (model A1673)
@"iPad6,4" :@"iPad Pro (9.7\")" // iPad Pro 9.7 inches - (models A1674 and A1675)
};
}
NSString* deviceName = [deviceNamesByCode objectForKey:code];
if (!deviceName) {
// Not found on database. At least guess main device type from string contents:
if ([code rangeOfString:@"iPod"].location != NSNotFound) {
deviceName = @"iPod Touch";
}
else if([code rangeOfString:@"iPad"].location != NSNotFound) {
deviceName = @"iPad";
}
else if([code rangeOfString:@"iPhone"].location != NSNotFound){
deviceName = @"iPhone";
}
else {
deviceName = @"Unknown";
}
}
UIDevice *device = [UIDevice currentDevice];
NSString *systemVersion = [device systemVersion];
return [NSString stringWithFormat:@"iOS#%@#%@",deviceName,systemVersion];
}複製程式碼
效果:
原專案地址: