如何使用NSInputStream和NSOutputStream

时间:2014-04-20 18:31:39

标签: ios cocoa-touch nsstream

我正在尝试在iPhone之间创建一个简单的多人回合制游戏。现在我想做的就是将一些字符串传递给我的方法,并让方法通过NSOutputStream发送字符串。我想我已使用NSNetServices正确关联了我的NSNetServiceBrowser。一旦他们连接,我的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做些什么的页面,但它们似乎都没有像我这样的初学者。我有几个问题。首先,如何设置一种方法,我将数据传递到(NSDataNSString)并通过self.outStream发送出去。我更喜欢解释代码的答案,而不仅仅是给我。其次,我应该在netService:didAcceptConnectionWithInputStream:outputStream:打开我的两个流,还应该scheduleInRunLoop NSOutputStream self.outStream`。最后,我做错了吗?

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

1 个答案:

答案 0 :(得分:-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 open ];
    [ uOStream open ];

    uQueue = NSMutableData.data;


    :
    :
    :

-   (void)
Send
{   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 ];
    }
}

-   (void)
Write:(NSData*)p
{   [ uQueue appendData:p ];
    if ( uOStream.hasSpaceAvailable ) [ self Send ];
}


-   (void)
stream:(NSStream*)pS
handleEvent:(NSStreamEvent)p
{   switch( p )
    {

    :
    :
    :

    case NSStreamEventHasSpaceAvailable:
        [ self Send ];
        break;
    }
}