网络编程错误
1. 操作系统错误
操作系统错误是由数据包没有达到预定目标导致的。数据包可能是建立连接的一部分,也可能位于连接建立的中间阶段。
OS错误可能由如下原因造成:
- 没有网络——可由Reachability框架检测到
- 无法路由到目标主机——有时可由操作系统迅速检测到,不过也有可能造成连接超时
- 没有应用监听目标端口
- 无法解析目标主机名——由配置错误或是尝试访问没有外部名字解析且处于隔离网络中的主机造成的
NSError
IOS通过NSError在软件组件中传递错误信息
NSError的创建:有3个主要属性:
- code——标识错误的NSInteger值,对于产生该错误的错误域来说该值是唯一的;
- domain——指定错误域的NSString指针,如NSPOSIXErrorDomain,NSOSStatusErrorDomain及NSMachErrorDomain;
- userInfo——NSDictionary指针,包含特定于错误的值。
NSMutableDictionary *errorDict = [NSMutableDictionary dictionary];
[errorDict setValue:@"错误信息" forKey:NSLocalizedDescriptionKey];
NSError *error = [NSError errorWithDomain:@"myDomain" code:-100 userInfo:errorDict];
Reachablitity
提供4个主要功能:
- 标识设备是否具备可用的网络连接
- 标识当前的网络连接是否可以到达某个特定的主机
- 标识当前使用的是哪种网络技术:WIFI、WWAN还是什么技术都没用
- 在网络状态发生变化时发出通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChanged:) name:kReachabilityChangedNotification object:nil];
Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
- (void)getNetWorkStatus:(Reachability *)reach {
NetworkStatus status = [reach currentReachabilityStatus];
switch (status) {
case NotReachable:
NSLog(@"NotReachable");
break;
case ReachableViaWiFi:
NSLog(@"wifi");
break;
case ReachableViaWWAN:
NSLog(@"wwan");
break;
default:
break;
}
}
之前,要判断当前网络是否能访问某特定主机可以这样用:
Reachability *reachability = [Reachability reachabilityWithHostName:@"访问的主机地址"];
if (reachability == NotReachable) {
}
但经过测试,在IOS10上(只在iOS10上试过),这种方法并不能真正判断出是否能访问特定主机,而是通过第三方框架RealReachability能达到这种目的。
#define GLobalRealReachability [RealReachability sharedInstance]
[GLobalRealReachability reachabilityWithBlock:^(ReachabilityStatus status) {
switch (status) {
case NotReachable: {
break;
}
case ReachableViaWiFi: {
break;
}
case ReachableViaWWAN: {
break;
}
default:
break;
}
2. HTTP错误
HTTP错误是由HTTP请求、HTTP服务器或者应用服务器的问题造成的,其错误通过HTTP响应的状态码发送给请求客户端。
- 100级别:来自于HTTP服务器的信息,表示请求的处理将会继续,不过带有警告
- 200级别:服务器成功请求了处理(204表请求成功,不过没有向客户端返回负载)
- 300级别:表示客户端必须执行某个动作才能继续请求,因为所需资源已移动
- 400级别:客户端错误,发出了服务端无法正确处理的数据。(404表示找不到URL指定的资源)
- 500级别:HTTP服务器与下游服务器之间出现了错误。如Web服务器调用了 JavaEE应用服务器,Servlet出现了NullPointerException,客户端则会收到500级别错误。
3. 应用错误
应用错误是由运行在服务层之上的业务逻辑和应用造成的。可能是代码问题(异常)、语义错误(向服务提供了无效账号)等。对于前者来说,建议生成HTTP500级别错误;而后者,应该在应用负载中返回错误码。
错误处理的经验法则
1. 在接口契约中应该指定如何向客户端发送错误信息;
2. 错误状态可能不正确,从移动设备发往服务器的任何网络请求都有3种可能结果:
- 设备完全能够确认操作是成功的
- 设备完全能够确认操作是失败的
- 设备模糊的确认操作是失败的。
如,应用发出在两个账户间转账的HTTP请求。请求被银行系统接收并正确处理;然而,由于网络失败应答却丢失了,NSURLConnect报告超时。超时发生了,但转账请求却成功处理了。如果重试该操作,那就会导致重复转账,可能还会造成账户透支。
这种场景会导致应用出现意外和检测不到的错误行为。
3. 验证负载
4. 分离错误与正常的业务状况
5. 总是检查HTTP状态
6. 总是检查NSError的值
7. 使用一致的方法来处理错误
8. 总是设置超时时间
IOS中,HTTP请求的默认超时时间间隔是4分钟,用户可以自定义超时时间间隔:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:@"URL" cachePolicy:NSURLCacheStorageAllowed timeoutInterval:20];
优雅地处理网络错误 |