我正在使用ftp协议下载文件。现在,为了检查处理错误的能力,我模拟了一些网络错误的发生。处理网络inputStream的代码如下:
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{
#pragma unused(aStream)
assert(aStream == self.networkStream);
switch (eventCode) {
case NSStreamEventOpenCompleted: {
self.connected = YES;
} break;
case NSStreamEventHasBytesAvailable: {
NSInteger bytesRead;
uint8_t buffer[32768];
// Pull some data off the network.
bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
DLog(@"%@,byteRead:%d",self.urlInput,bytesRead);
if (bytesRead == -1) {
[self _stopReceiveWithStatus:@"Network read error"];
} else if (bytesRead == 0) {
[self _stopReceiveWithStatus:@"success"];
} else {
NSInteger bytesWritten;
NSInteger bytesWrittenSoFar;
bytesWrittenSoFar = 0;
do {
bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:bytesRead - bytesWrittenSoFar];
DLog(@"%@,bytesWritten:%d",self.urlInput,bytesWritten);
assert(bytesWritten != 0);
if (bytesWritten == -1) {
[self _stopReceiveWithStatus:@"File write error"];
break;
} else {
bytesWrittenSoFar += bytesWritten;
}
} while (bytesWrittenSoFar != bytesRead);
}
} break;
case NSStreamEventHasSpaceAvailable: {
assert(NO); // should never happen for the output stream
} break;
case NSStreamEventErrorOccurred: {
[self _stopReceiveWithStatus:@"Stream open error"];
} break;
case NSStreamEventEndEncountered: {
assert(NO);
} break;
default: {
assert(NO);
} break;
}
}
如果我手动关闭wifi或关闭无线路由器(网络连接标志关闭),将返回“NSStreamEventErrorOccurred”,下载过程将正确终止。但是,如果我关闭调制解调器,同时保持无线路由器打开(网络连接标志打开)。下载过程停留在“NSStreamEventHasBytesAvailable”的情况下。即使在我打开互联网连接后,它仍然卡住了。
我想知道它为什么会被卡住,我怎么能检测到这种错误。我该如何处理这种情况?
答案 0 :(得分:1)
首先,感谢您考虑这个并运行测试。许多开发人员认为“网络连接将始终有效。”
其次,使用NSStream
进行FTP下载似乎有点奇怪;你知道NSURLConnection
支持FTP,对吧?除非你做的事情很奇怪,否则你应该使用内置的URL loading facilities。
在任何情况下,这里的问题是,in principle无法让应用程序(或计算机)确定连接是否有暂停,因为连接失败(应该重新启动或取消)或者因为它只是运行缓慢(在这种情况下需要耐心)。
当你的调制解调器重新连接时,我没有恢复活动的TCP会话,这有点让我感到惊讶。这表明,当调制解调器链路断开或者你的IP在重新连接时正在改变时,你的ISP的路由器可能正在断开连接,但这对你的问题来说并不重要。
TCP会话通常最终会在一段时间不活动后由操作系统(或上游路由器)超时,但这可能是一个不可接受的长时间。所以你可能需要做的是实现超时。
我可能会做的事情(假设你按照上面讨论的那样坚持NSStream
)会定期NSTimer
开火 - 可能每15秒一次 - 然后让回调比较当前时间到您在每个NSStreamEventHasBytesAvailable
事件上设置的时间戳。如果时间戳太旧(例如,超过15秒),请根据需要取消或重新启动下载并通知用户。
但是,请再看一下,使用NSURLConnection
。