2025-04-30

1.Ping域名、Ping某IP

有時候可能會遇到ping 某個域名或者ip通不通,再做下一步操作。這裡的ping與傳統的做get或者post請求還是有很大區別的。比如我們連接瞭某個WiFi,測試ping www.baidu.com,如果能ping 通,基本可以斷定可以上網瞭,但是如果我們做瞭一個get 請求(url 是www.baidu.com),路由器可能重定向這個WiFi內的某網頁瞭,依然沒有錯誤返回,就會誤認為可以正常上網。

這裡有關於ping命令的詳細解釋:百度百科Ping

iOS中想要ping域名或者ip,蘋果提供瞭一個官方例子SimplePing

在例子中,有一個蘋果已經封裝過的類【SimplePing.h】和【SimplePing.m】

使用起來也相當的簡單:

首先創建一個Ping對象:

SimplePing*pinger=[[SimplePingalloc]initWithHostName:self.hostName]; self.pinger=pinger; pinger.delegate=self; pinger.addressStyle=SimplePingAddressStyleICMPv4; [pingerstart];

然後在start成功的代理方法中,發送數據報文:

/** *start成功,也就是準備工作做完後的回調 */ -(void)simplePing:(SimplePing*)pingerdidStartWithAddress:(NSData*)address { //發送測試報文數據 [self.pingersendPingWithData:nil]; } -(void)simplePing:(SimplePing*)pingerdidFailWithError:(NSError*)error { NSLog(@"didFailWithError"); [self.pingerstop]; }

其他幾個代理方法也非常簡單,就簡單記錄一下:

//發送測試報文成功的回調方法 -(void)simplePing:(SimplePing*)pingerdidSendPacket:(NSData*)packetsequenceNumber:(uint16_t)sequenceNumber { NSLog(@"#%usent",sequenceNumber); } //發送測試報文失敗的回調方法 -(void)simplePing:(SimplePing*)pingerdidFailToSendPacket:(NSData*)packetsequenceNumber:(uint16_t)sequenceNumbererror:(NSError*)error { NSLog(@"#%usendfailed:%@",sequenceNumber,error); } //接收到ping的地址所返回的數據報文回調方法 -(void)simplePing:(SimplePing*)pingerdidReceivePingResponsePacket:(NSData*)packetsequenceNumber:(uint16_t)sequenceNumber { NSLog(@"#%ureceived,size=%zu",sequenceNumber,packet.length); } -(void)simplePing:(SimplePing*)pingerdidReceiveUnexpectedPacket:(NSData*)packet { NSLog(@"#%s",__func__); }

註意點:

iOS 中 ping失敗後(即發送測試報文成功後,一直沒後收到響應的報文),不會有任何回調方法告知我們。而一般ping 一次的結果也不太準確,ping 花費的時間也非常短,所以我們一般會ping多次,發送一次ping 測試報文0.5s後檢測一下這一次ping是否已經收到響應。0.5s後檢測時,如果已經收到響應,則可以ping 通;如果沒有收到響應,則視為超時。

做法也有很多種,可以用NSTimer或者 {- (void)performSelector: withObject:afterDelay:}

這裡有一個別人寫的工程:https://github.com/lovesunstar/STPingTest

727768-ff8ab7124905812e.jpg

PingTest效果圖

727768-6d4c781945dd1334.jpg

終端ping效果圖

2.獲取WiFi信息

以前物聯網剛火的時候,出現過很多一體式無線路由,所以App裡難免會遇到要判斷當前所連接的WiFi,以及獲取WiFi信息的功能。13年的時候查過一些關於WiFi的方法,後面漸漸都忘記瞭。慚愧!!!

需要添加SystemConfiguration.framework 並在當前類中添加代碼

#importarpa/inet.h>

#importnetinet/in.h>

#importifaddrs.h>

//獲取WiFi信息,返回的字典中包含瞭WiFi的名稱、路由器的Mac地址、還有一個Data(轉換成字符串打印出來是wifi名稱) -(NSDictionary*)fetchSSIDInfo{ NSArray*ifs=(__bridge_transferNSArray*)CNCopySupportedInterfaces(); if(!ifs){ returnnil; } NSDictionary*info=nil; for(NSString*ifnaminifs){ info=(__bridge_transferNSDictionary*)CNCopyCurrentNetworkInfo((__bridgeCFStringRef)ifnam); if(info&&[infocount]){break;} } returninfo; } //打印出來的結果: 2016-05-1215:28:51.674SimplePing[18883:6790207]WIFI_INFO:{ BSSID="a4:2b:8c:c:7f:bd"; SSID=bdmy06; SSIDDATA=; }

3.獲取WiFi名稱

有瞭上一步,獲取WiFi名稱就非常簡單瞭。

NSString*WiFiName=info[@"SSID"]; //打印結果: 2016-05-1215:35:13.059SimplePing[18887:6791418]bdmy06

完整的:

-(NSString*)fetchWiFiName{ NSArray*ifs=(__bridge_transferNSArray*)CNCopySupportedInterfaces(); if(!ifs){ returnnil; } NSString*WiFiName=nil; for(NSString*ifnaminifs){ NSDictionary*info=(__bridge_transferNSDictionary*)CNCopyCurrentNetworkInfo((__bridgeCFStringRef)ifnam); if(info&&[infocount]){ //這裡其實對應的有三個key:kCNNetworkInfoKeySSID、kCNNetworkInfoKeyBSSID、kCNNetworkInfoKeySSIDData, //不過它們都是CFStringRef類型的 WiFiName=[infoobjectForKey:(__bridgeNSString*)kCNNetworkInfoKeySSID]; //WiFiName=[infoobjectForKey:@"SSID"]; break; } } returnWiFiName; }

4.獲取當前所連接WiFi的網關地址

例如自己傢的路由器一般默認的網關地址是192.168.1.1,獲取的就是這個192.168.1.1。

為什麼不直接寫死呢?

因為一些商場或者有多個路由器的網關地址是不一樣的,比如之前有個公司的網關是192.168.89.1。

這裡有篇博客,這是地址

需要導入的庫:

#import#import#import

獲取網關的方法

-(NSString*)getGatewayIpForCurrentWiFi{ NSString*address=@"error"; structifaddrs*interfaces=NULL; structifaddrs*temp_addr=NULL; intsuccess=0; //retrievethecurrentinterfaces-returns0onsuccess success=getifaddrs(&interfaces); if(success==0){ //Loopthroughlinkedlistofinterfaces temp_addr=interfaces; //*/ while(temp_addr!=NULL){ /*/ inti=255; while((i–)>0) //*/ if(temp_addr->ifa_addr->sa_family==AF_INET){ //Checkifinterfaceisen0whichisthewificonnectionontheiPhone if([[NSStringstringWithUTF8String:temp_addr->ifa_name]isEqualToString:@"en0"]) { //GetNSStringfromCString//ifa_addr //ifa->ifa_dstaddristhebroadcastaddress,whichexplainsthe"255's" //address=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_dstaddr)->sin_addr)]; address=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)]; //routerIP—-192.168.1.255廣播地址 NSLog(@"broadcastaddress–%@",[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_dstaddr)->sin_addr)]); //–192.168.1.106本機地址 NSLog(@"localdeviceip–%@",[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)]); //–255.255.255.0子網掩碼地址 NSLog(@"netmask–%@",[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_netmask)->sin_addr)]); //–en0端口地址 NSLog(@"interface–%@",[NSStringstringWithUTF8String:temp_addr->ifa_name]); } } temp_addr=temp_addr->ifa_next; } } //Freememory freeifaddrs(interfaces); in_addr_ti=inet_addr([addresscStringUsingEncoding:NSUTF8StringEncoding]); in_addr_t*x=&i; unsignedchar*s=getdefaultgateway(x); NSString*ip=[NSStringstringWithFormat:@"%d.%d.%d.%d",s[0],s[1],s[2],s[3]]; free(s); returnip; }

其中 getdefaultgateway 是一個C語言文件中的方法,在工程裡可以找到。

5.獲取本機在WiFi環境下的IP地址

獲取本機在WiFi環境下的ip地址,在上一節中其實已經寫過,這裡將其提取出來即可:

-(NSString*)getLocalIPAddressForCurrentWiFi { NSString*address=nil; structifaddrs*interfaces=NULL; structifaddrs*temp_addr=NULL; intsuccess=0; //retrievethecurrentinterfaces-returns0onsuccess success=getifaddrs(&interfaces); if(success==0){ //Loopthroughlinkedlistofinterfaces temp_addr=interfaces; while(temp_addr!=NULL){ if(temp_addr->ifa_addr->sa_family==AF_INET){ //Checkifinterfaceisen0whichisthewificonnectionontheiPhone if([[NSStringstringWithUTF8String:temp_addr->ifa_name]isEqualToString:@"en0"]){ address=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)]; returnaddress; } } temp_addr=temp_addr->ifa_next; } freeifaddrs(interfaces); } returnnil; }

同樣的方式也可以獲取廣播地址、子網掩碼、端口等,組裝成一個字典。

-(NSMutableDictionary*)getLocalInfoForCurrentWiFi{ NSMutableDictionary*dict=[NSMutableDictionarydictionary]; structifaddrs*interfaces=NULL; structifaddrs*temp_addr=NULL; intsuccess=0; //retrievethecurrentinterfaces-returns0onsuccess success=getifaddrs(&interfaces); if(success==0){ //Loopthroughlinkedlistofinterfaces temp_addr=interfaces; //*/ while(temp_addr!=NULL){ if(temp_addr->ifa_addr->sa_family==AF_INET){ //Checkifinterfaceisen0whichisthewificonnectionontheiPhone if([[NSStringstringWithUTF8String:temp_addr->ifa_name]isEqualToString:@"en0"]){ //—-192.168.1.255廣播地址 NSString*broadcast=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_dstaddr)->sin_addr)]; if(broadcast){ [dictsetObject:broadcastforKey:@"broadcast"]; } NSLog(@"broadcastaddress–%@",broadcast); //–192.168.1.106本機地址 NSString*localIp=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_addr)->sin_addr)]; if(localIp){ [dictsetObject:localIpforKey:@"localIp"]; } NSLog(@"localdeviceip–%@",localIp); //–255.255.255.0子網掩碼地址 NSString*netmask=[NSStringstringWithUTF8String:inet_ntoa(((structsockaddr_in*)temp_addr->ifa_netmask)->sin_addr)]; if(netmask){ [dictsetObject:netmaskforKey:@"netmask"]; } NSLog(@"netmask–%@",netmask); //–en0端口地址 NSString*interface=[NSStringstringWithUTF8String:temp_addr->ifa_name]; if(interface){ [dictsetObject:interfaceforKey:@"interface"]; } NSLog(@"interface–%@",interface); returndict; } } temp_addr=temp_addr->ifa_next; } } //Freememory freeifaddrs(interfaces); returndict; }

將返回的字典打印出來:

2016-05-1217:59:09.257SimplePing[19141:6830567]wifi:{ broadcast="192.168.1.255"; interface=en0; localIp="192.168.1.7"; netmask="255.255.255.0"; }

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *