iOS: outputStream does not stay open

2019-06-11 15:12发布

问题:

Okay so I'm implementing a NSOutput and Input Streams. When they are initialized, the streams open and connect to my TCPServer I have running on my PC, but then appear to close once outside of the initializing function or maybe the streams aren't being stored properly. I'm not quite sure so any assistance is greatly appreciated

In my .h file:

@interface AVCamViewController : UIViewController <UIImagePickerControllerDelegate,UINavigationControllerDelegate, NSStreamDelegate> {
    NSOutputStream *outputStream;
    NSInputStream *inputStream;
}

@property (retain) NSInputStream *inputStream;
@property (retain) NSOutputStream *outputStream;

In my .m file:

@synthesize inputStream, outputStream;

    -(void)sendaResponse
    {
        NSString *response = [NSString stringWithFormat:@"Hello from Ipad Simulator"];
        NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
        [outputStream write:[data bytes] maxLength:[data length]];
        NSLog(@"%u", outputStream.streamStatus);
    }

    -(void)initNetworkCommunication
    {
        CFReadStreamRef readStream;
        CFWriteStreamRef writeStream;
        CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"10.9.100.122", 80, &readStream, &writeStream);

        NSInputStream *inputStream = (NSInputStream *) readStream;
        NSOutputStream *outputStream = (NSOutputStream *) writeStream;

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


        NSLog(@"%u and %u", inputStream.streamStatus, outputStream.streamStatus);
        NSString *response = [NSString stringWithFormat:@"Hello from Mikes Ipad Simulator"];
        NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
        [outputStream write:[data bytes] maxLength:[data length]];
        NSLog(@"%u", outputStream.streamStatus);
    }

    -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
    {
        switch (eventCode) {
            case NSStreamEventOpenCompleted:
                NSLog(@"Stream Opened %u", outputStream.streamStatus);
                break;

            case NSStreamEventHasBytesAvailable:
                if(aStream == inputStream)
                {
                    uint8_t buffer [1024];
                    int len;

                    while ([inputStream hasBytesAvailable])
                    {
                        len = [inputStream read:buffer maxLength:sizeof(buffer)];
                        if(len>0)
                        {
                            NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                            if(nil != output)
                            {
                                NSLog(@"Server said: %@", output);
                            }
                        }
                    }
                }
                break;

            case NSStreamEventErrorOccurred:
                NSLog(@"Can not connect to the host!");
                break;

            case NSStreamEventEndEncountered:
                if(aStream == inputStream)
                    NSLog(@"Ending input stream");
                if(aStream == outputStream)
                    NSLog(@"Ending output stream");

                [aStream close];
                [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
                [aStream release];
                aStream = nil;
                break;

            default:
                break;
        }
    }

In the initNetworkConnection the simulator connects to my TCPServer and opens a connection(streamstatus = 2). Receives the message "Hello from Ipad Simulator". But then I have the "sendaResponse" method called from a button click which then streamstatus = 0 and "outputstream" doesn't appear to be initialized. Am I just not retaining the variable properly?

回答1:

I'm assuming you're using ARC. Remove this code:

{
NSOutputStream *outputStream;
NSInputStream *inputStream;
}

@synthesize inputStream, outputStream;

It's just confusing you between the properties and the instance variables. And the result of having it is that you're setting the instance variable directly and your stream instances are being deallocated by ARC.

Instead, once you've deleted that code above, access the streams with self.inputStream and self.outputStream. This will allow the properties to work properly and ensure that the 'retain' spec that you configure is respected.

Your original code might also just not be trying to set the properties... Your configuration should be:

    NSInputStream *inputStream = (NSInputStream *) readStream;
    NSOutputStream *outputStream = (NSOutputStream *) writeStream;

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

self.inputStream = inputStream;
self.outputStream = outputStream;

Then change the property to:

@property (strong) NSInputStream *inputStream;
@property (strong) NSOutputStream *outputStream;