0

我正在使用 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”的情况下。即使我打开互联网连接,它仍然卡住。

我想知道它为什么卡住以及如何检测到这种错误。我该如何处理这种情况?

4

1 回答 1

1

首先,感谢考虑这一点并运行测试。许多开发人员假设“网络连接将始终有效”。

NSStream其次,您使用FTP 下载似乎有点奇怪;你知道NSURLConnection支持FTP,对吧?除非您正在做一些非常奇怪的事情,否则您应该使用内置的URL 加载工具

在任何情况下,这里的问题是原则上应用程序(或计算机)无法确定连接中是否存在暂停,因为连接失败(并且应该重新启动或取消)或者因为它只是运行缓慢(在这种情况下需要耐心)。

当你的调制解调器重新连接时,活动的 TCP 会话没有恢复,我有点惊讶。这表明当调制解调器链路断开或您的 IP 在重新连接时发生变化时,您的 ISP 的路由器可能会断开连接,但这对您的问题并不重要。

TCP 会话通常最终会在一段时间不活动后被操作系统(或上游路由器)超时,但这可能是一个不可接受的长时间。所以你可能需要做的就是实现一个超时。

What I'd probably do (assuming you stay the course with NSStream as discussed above) is have an NSTimer firing off periodically - maybe every 15 seconds - and have the callback compare the current time to a timestamp that you set on each NSStreamEventHasBytesAvailable event. If the timestamp is too old (say, more than 15 seconds), cancel or restart the download as desired and notify the user.

But again, take a look at just using NSURLConnection.

于 2012-07-06T02:10:20.133 回答