问题:
最近在app发布之后, 有用户反映有无法打开某些界面的问题. 明明网络是通的,但就是无法从服务器取得数据,在开发环境无法复现。这时候很可能是用户所在的网络的DNS 服务器, 无法正确解析app的http api的域名.
我们假设api的域名为:api.hahaha.com
app的一个网络请求, 可能会是这种格式:
对于域名api.hahaha.com, DNS的错误解析可能有两种:
- 无法解析, 无法得到IP
- 错误解析, 返回错误IP
解决方法:
- 在发布app时, 内置一个默认IP, 例如
192.168.88.63
; - 在启动时, 或者网络连通性变化时, 解析域名;
+ (NSString *)getIPAddress:(NSString*) hostname{
Boolean result;
CFHostRef hostRef;
CFArrayRef addresses;
NSString *ipAddress = @"";
hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)hostname);
if (hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
if (result == TRUE) {
addresses = CFHostGetAddressing(hostRef, &result);
}
}
if (result == TRUE) {
CFIndex index = 0;
CFDataRef ref = (CFDataRef) CFArrayGetValueAtIndex(addresses, index);
struct sockaddr_in* remoteAddr;
char *ip_address;
remoteAddr = (struct sockaddr_in*) CFDataGetBytePtr(ref);
if (remoteAddr != NULL) {
ip_address = inet_ntoa(remoteAddr->sin_addr);
}
ipAddress = [NSString stringWithCString:ip_address encoding:NSUTF8StringEncoding];
}
return ipAddress;
}
- 检查解析的结果
3.1 如果不能解析, 使用一个默认的IP地址代替域名;
之后的网络请求为: https://192.168.88.63/login
3.2 如果解析成功,例如是192.168.87.62
,为了防止解析结果错误,可以采用一个检测接口, 调用后,根据其响应(Http Response)内容, 检查域名中的api接口是否正常;
https://api.hahaha.com/test
response: {state: "Im ok"}
3.2.1 如果api正常, 则使用域名进行请求. 并且将默认IP改为192.168.87.62
, 作为下次备用.
之后的网络请求为: https://api.hahaha.com/login
3.2.2 如果域名不正常, 则使用默认IP
之后的网络请求为: https://192.168.88.63/login
- 将域名或者IP设置为AFHTTPSessionManager的BaseURL进行正常的网络请求