【问题标题】:iOS how can i perform multiple NSInputStreamiOS 如何执行多个 NSInputStream
【发布时间】:2015-11-07 21:12:37
【问题描述】:

我的应用使用 NSInputStream,如下所示:

inputStream.delegate = self;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [readStream open];

和委托:

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent

它工作正常,但我做的所有其他请求,它排队,直到第一个完成。 我可以一次做一个,没有办法做多个并发请求。

有解决办法吗? 谢谢你

此解决方案不适用于我: https://stackoverflow.com/a/15346292/1376961

更新: 我的服务器是否无法处理来自同一来源的多个连接。

【问题讨论】:

    标签: ios nsthread nsstream nsinputstream nsoutputstream


    【解决方案1】:

    您可以尝试将每个流安排在其自己的运行循环中。下面是来自the mock 类的精炼方法,旨在对我的POSInputStreamLibrary 进行单元测试:

    static const NSTimeInterval kRunLoopCycleInterval = 0.01f;
    static const uint64_t kDispatchDeltaNanoSec = 250000000;
    
    - (POSRunLoopResult)launchNSRunLoopWithStream:(NSInputStream *)stream delegate:(id<NSStreamDelegate>)streamDelegate {
        stream.delegate = streamDelegate;
        __block BOOL breakRunLoop = NO;
        __block dispatch_semaphore_t doneSemaphore = dispatch_semaphore_create(0);
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            [stream scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];
            if ([stream streamStatus] == NSStreamStatusNotOpen) {
                NSLog(@"%@: opening stream...", [NSThread currentThread]);
                [stream open];
            }
            while ([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:kRunLoopCycleInterval]] && !breakRunLoop)
            {}
            NSLog(@"%@: We are done!", [NSThread currentThread]);
            dispatch_semaphore_signal(doneSemaphore);
        });
        POSRunLoopResult result = dispatch_semaphore_wait(doneSemaphore, dispatch_time(DISPATCH_TIME_NOW, kDispatchDeltaNanoSec)) == 0 ? POSRunLoopResultDone : POSRunLoopResultTimeout;
        if (POSRunLoopResultTimeout == result) {
            breakRunLoop = YES;
            dispatch_semaphore_wait(doneSemaphore, DISPATCH_TIME_FOREVER);
        }
        return result;
    }
    

    【讨论】:

      【解决方案2】:

      您需要在单独的线程中创建流,以使它们能够同时工作。我假设您有一个方法可以设置您提到的 inputStream:

      - (void)openStreamInNewThread {
          [NSThread detachNewThreadSelector:@selector(openStream) toTarget:self withObject:nil];
      }
      
      - (void)openStream {
          NSInputStream *inputStream;
      
          // stream  setup
      
          [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                         forMode:NSRunLoopCommonModes];
      }
      

      注意[NSRunLoop currentRunLoop]会返回当前线程的runloop。因此,您可以让新创建的流在单独的线程中运行,同时在它们自己的线程中加载数据。

      【讨论】:

      • 究竟是什么不起作用?委托方法不是全部或仅称为提供数据的方法吗?您是否尝试多次连接到同一个地址和端口?
      • 每次只有一个操作工作,当1完成第二次启动时。我想要所有 NSInputStream 下载,是的,相同的端口和相同的主机,但不是相同的 ftp 文件/url
      • 您能否确认您的服务器可以处理来自同一来源的多个连接?
      • 使用桌面 ftp 客户端我可以下载多个文件,我该如何检查呢?
      • 您的桌面客户端可能使用主动 FTP,它通过不同的端口连接,也从服务器连接到客户端。看看我和 nkreipke 通过 github 发布的 FTP 类,你应该通过他的用户资料找到它
      【解决方案3】:

      每次创建新的 NSInputStream 时,我都会将其添加到块对象中,然后将块对象存储在 NSMutableArray 中。

      我发布了将视频从一个 iOS 流式传输到另一个 iOS 的代码:

      https://app.box.com/s/94dcm9qjk8giuar08305qspdbe0pc784

      使用 Xcode 11 构建此应用;在两台 iOS 11 设备上运行它。

      触摸两台设备之一上的相机图标以开始流式传输实时视频。

      如果您没有两台设备,可以在模拟器中运行应用;但是,只能从真实设备流式传输(相机在模拟器上不可用)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-19
        • 1970-01-01
        • 2018-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多