【问题标题】:How to use NSInputStream and NSOutputStream如何使用 NSInputStream 和 NSOutputStream
【发布时间】:2014-06-04 20:29:43
【问题描述】:

我正在尝试在 iPhone 之间创建一个简单的多人回合制游戏。现在我要做的就是将一些字符串传递给我的方法,并让方法通过NSOutputStream 发送字符串。我想我已经使用NSNetServiceBrowser 正确连接了我的NSNetServices。一旦他们连接,我的NSNetServiceDelegate 就会调用netService:didAcceptConnectionWithInputStream:outputStream:,这应该给我我的 i/o NSStream 对。我的方法是这样的:

-(void)netService:(NSNetService *)sender didAcceptConnectionWithInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream{
    [self.myNet getInputStream:&inputStream outputStream:&outputStream];
    self.inStream = inputStream;
    self.outStream = outputStream;
    [self.inStream setDelegate:self];
    [self.inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.inStream open];
}

我想我已经正确设置了 NSInputStream。我还有一个 NSStream 的代表,它正在实现stream:handleEvent:

看起来像这样:

-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
    NSInputStream *inStream = (NSInputStream *)aStream;
    BOOL shouldClose = NO;
    switch(eventCode) {
        case  NSStreamEventEndEncountered:
            shouldClose = YES;
            // If all data hasn't been read, fall through to the "has bytes" event
            if(![inStream hasBytesAvailable]) break;
        case NSStreamEventHasBytesAvailable: ; // We need a semicolon here before we can declare local variables
            uint8_t *buffer;
            NSUInteger length;
            BOOL freeBuffer = NO;
            // The stream has data. Try to get its internal buffer instead of creating one
            if(![inStream getBuffer:&buffer length:&length]) {
                // The stream couldn't provide its internal buffer. We have to make one ourselves
                buffer = malloc(BUFFER_LEN * sizeof(uint8_t));
                freeBuffer = YES;
                NSInteger result = [inStream read:buffer maxLength:BUFFER_LEN];
                if(result < 0) {
                    // error copying to buffer
                    break;
                }
                length = result;
            }
            // length bytes of data in buffer
            if(freeBuffer) free(buffer);
            break;
        case NSStreamEventErrorOccurred:
            // some other error
            shouldClose = YES;
            break;
        case NSStreamEventHasSpaceAvailable:
            break;
        case NSStreamEventNone:
            break;
        case NSStreamEventOpenCompleted:
            break;
    }
    if(shouldClose){
        [inStream close];
    }
}

我从:this page 获取了该代码。在该代码中,aStream 应该是 self.inStream。我查看了描述如何处理 NSOutputStream 的页面,但它们似乎都不适合像我这样的初学者。我有几个问题。首先,我如何设置一个方法,将数据传入(NSData 或者NSString)并通过self.outStream 发送出去。我更喜欢解释代码的答案,而不是仅仅给我。其次,我应该在netService:didAcceptConnectionWithInputStream:outputStream: 中打开我的两个流,我还应该在scheduleInRunLoop NSOutputStreamself.outStream` 中打开我的两个流吗?最后,我做错了吗?

感谢您的回答。这也是我的第一个问题,因此欢迎任何建设性的批评。

【问题讨论】:

    标签: ios cocoa-touch nsstream


    【解决方案1】:

    要写入输出流,请检查流是否有可用空间并使用写入数据

    - (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)length

    所以,代码可能如下所示。

    if ( self.outStream.hasSpaceAvailable ) [ self.outStream write:... maxLength: ];

    如果输出流没有可用空间,稍后

    -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode

    输出流的委托方法会调用 eventCode = NSStreamEventHasSpaceAvailable。

    您应该打开输出流并将其安排在 netService:didAcceptConnectionWithInputStream:outputStream 或当您收到输入流的 NSStreamEventOpenCompleted 时。两者都可以。

    如果你不想写阻塞线程,你需要准备队列。

    所以代码如下

    NSMutableData* uQueue; NSInputStream* uIStream; NSOutputStream* uOStream; : : : uIStream.delegate = self; uOStream.delegate = self; [ uIStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode ]; [ uOStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode ]; [ uIStream 打开 ]; [uOStream 打开]; uQueue = NSMutableData.data; : : : - (空白) 发送 { if ( uQueue.length ) { NSInteger wLength = [ uOStream write:(const uint8_t*)uQueue.bytes maxLength:uQueue.length ]; if ( wLength > 0 ) [ uQueue replaceBytesInRange:NSMakeRange( 0, wLength ) withBytes:NULL length:0 ]; } } - (空白) 写:(NSData *)p { [ uQueue appendData:p ]; if ( uOStream.hasSpaceAvailable ) [ 自发送 ]; } - (空白) 流:(NSStream*)pS 处理事件:(NSStreamEvent)p { 开关( p ) { : : : 案例 NSStreamEventHasSpaceAvailable: [自我发送]; 休息; } }

    【讨论】:

    • 谢谢。但是,我不完全确定Write: 的用途它似乎与stream:handleEvent: 做同样的事情另外,我是否需要一个 if 语句来检查我在stream:handleEvent: 中处理的流是否是@ 987654324@ 或 NSOutputStream?
    • 使用 Write: 发送数据。你想用 stream:handleEvent: 发送数据吗?
    • 如果数据有 10Kbytes 并且你的输出流每次调用只能发送 5K 字节,剩余的 5K 数据将保存在 uQueue 中,当你收到 NSStreamEventHasSpaceAvailable 时发送。
    • 如果您的输入流和输出流的委托相同,您可能需要检查您的流。
    • 我正在发送图像,它被分割成不同的数据块,但是在接收端如何知道整个图像被传输并且它可以使用数据来创建它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多