在后台线程上执行工作后写入NSOutputStream不起作用

时间:2016-07-19 16:11:25

标签: ios cocoa-touch nsstream nsinputstream nsoutputstream

我有一个程序在一些初始处理后通过NSStreams发送大文件。应用程序的流程如下:

1)两台设备相互连接,打开输入和输出流,并安排运行循环:

    [self.inputStream  setDelegate:self];
    [self.outputStream setDelegate:self];
    [self.inputStream  scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [self.inputStream  open];
    [self.outputStream open];

2)服务器设备向客户端发送一条消息,表明一切正常,我们都准备好了。客户端收到此消息就好了。

3)然后,客户端选择要发送到服务器的文件列表,然后点击“发送”。然后客户端旋转后台线程以获取一堆文件并将它们全部压缩。这可能需要一分钟左右的时间。

- (void) sendFilesAtPaths: (NSArray *) paths
{
    self.paths = [paths copy];

    __weak FileSharingClient *weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(Item *item in weakSelf.paths)
        {
            //Zip files up, this can take some time but we're on a background thread so it won't lock up the UI
            [weakSelf.connection zipFilesAssociatedWithItem:item];
        }

        //Now that we've done all the heavy work, bounce back to the main thread to actually start sending the data
        dispatch_async(dispatch_get_main_queue(), ^{
            //Start by sending only the first file, the server will let us know when they are ready for the next one
            [weakSelf.connection sendFileWithItem:weakSelf.paths.firstObject];
        });
    });



}

4)对'sendFileWithItem:'的调用通过进行以下调用来传递第一个信息:

if([_outputStream hasSpaceAvailable])
{
    NSInteger written = [self.outputStream write:buffer maxLength:self.outputHeaderSize];

}

通过拨打- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent

的电话发送数据,传输以下所有数据

问题

我在这里看到的问题是,如果压缩这些文件的后台线程花费更长的时间,则写入数据的初始调用DOES表示字节被写入流,但我从未收到任何调用进入- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent。服务器永远不会收到信息。大约30秒后,写命令(我假设?)超时,客户端收到一个空字符串(不是我从服务器显式发送的),客户端的连接关闭。

如果我发送的文件不需要很长时间来压缩,我就不会发现这个问题。

在主线程上运行所有内容 - 包括压缩过程 - 并不能解决问题(即使忽略了它锁定UI的事实)。这似乎排除了线程问题,但现在我必须继续进行。

我完全没有想法,我希望有人可以帮助我。

注意:在预期此建议时,我无法使用CocoaAsyncSockets库。

1 个答案:

答案 0 :(得分:0)

如果有人偶然发现这件事,我碰巧看到了同样的事情(并且认为同样的问题是这个问题):

问题不在于线程导致问题 - 只是写这篇文章让我意识到自己有多荒谬。问题似乎是在等待这么长时间接收数据后,底层TCP套接字超时。我通过每秒发送一次心跳消息解决了这个问题,这使得套接字保持活动状态,直到我准备好开始发送数据。