2

So I have both an input stream and an output stream and they are setup as the code provided below. The input stream's delegate method NSStreamEventHasBytesAvailable is called only when i write somedata onto the output stream. Why is that?

// connect to the server and bind the input/output streams
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, _serverAddr, _serverPort,
                                   &readStream, &writeStream);

_inputStream = (__bridge_transfer NSInputStream *)readStream;
_outputStream = (__bridge_transfer NSOutputStream *)writeStream;

// attach the streams to the current processor run loop
[_inputStream setDelegate:self];    

dispatch_async(_inputStreamQueue, ^{
    [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                            forMode:NSRunLoopCommonModes];

    [_inputStream open];
    [[NSRunLoop currentRunLoop] run];
});


dispatch_async(_outputStreamQueue, ^{
    [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                             forMode:NSRunLoopCommonModes];
    [_outputStream open];
    [[NSRunLoop currentRunLoop] run];
});

InputStreamDelegate

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
dispatch_async(dispatch_get_main_queue(), ^(void) {
    if (stream == _inputStream) {
        [self inputStreamHandleEvent:eventCode];
    }
});

}

 - (void)inputStreamHandleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
    case NSStreamEventHasSpaceAvailable:
    {
        break;
    }
    case NSStreamEventEndEncountered:
    {
        break;
    }

    case NSStreamEventNone:
    {
        break;
    }

    case NSStreamEventErrorOccurred:
    {
        NSLog(@"NSStreamEventErrorOccurred");
        NSError* error = [_inputStream streamError];
        NSString* errorMessage = [NSString stringWithFormat:@"%@ (Code = %ld)",
                                  [error localizedDescription],
                                  (long)[error code]];
        UIAlertView *wifiLostAlert = [[UIAlertView alloc]
                                      initWithTitle:@"Input Stream Error"
                                      message:errorMessage
                                      delegate:nil
                                      cancelButtonTitle:@"Continue"
                                      otherButtonTitles:nil];
        [wifiLostAlert show];

        break;
    }

    case NSStreamEventHasBytesAvailable:
    {
        uint8_t buf[1024];
        int read = 0;

        while ([_inputStream hasBytesAvailable])
        {
            read = [(NSInputStream *)_inputStream read : buf maxLength : 1024];
            if (read > 0)
            {
                NSLog(@"%d bytes read from the input stream.", read);
                [_recvBuf appendBytes:(const void *)buf length:read];
                int processedBytes = 0;
                do
                    {
                        processedBytes = [self processPacket];
                    }
                while (processedBytes > 0);
            }

            else
            {
                NSLog(@"End of the stream reached, or a socket error. Disconnecting.");
                [self disconnect];
            }
        }
        break;
    }

    case NSStreamEventOpenCompleted:
    {
        break;
    }
}

}

My problem:

So, for the inputStream, I read the received data through the callbacks. This does not happen all the time. When ever the server responds back, it's not reading the result. The input stream seems to work ONLY when I send some data through the output stream, and then it reads the input stream values for the previous communication.

In terms of logical sequence...

What I expect is this.

1 --> 1'

2 --> 2'

3 --> 3'

This is reality

1 -->

2 --> 1'

3 --> 2'

Legolas
  • 12,145
  • 12
  • 79
  • 132
  • How are you handling the inputstream delegate status? "NSStreamStatus", additionally, to rule out that it has nothing to do with your operation queues you might wanna run everything on the main run loop (instead of creating different threads for each of your queues) at first. – Pochi Feb 25 '14 at 04:58
  • Yes i have run them on the main thread. Same problem. Does not resolve anything. – Legolas Feb 25 '14 at 05:00
  • could you show your inputstream delegate's method? – Pochi Feb 25 '14 at 05:06
  • done...... check it out. – Legolas Feb 25 '14 at 05:08
  • Well first, you cant be sure about which will happen first (the input or the output) since they are running on different threads and different run loops. I think you should schedule them without the dispatch async call like this: https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI second, asynchronously dispatching to the main queue within the delegate could also cause issues. Third, try nslogging the inputStreamHandleEvent directly to see when it is actually being called. – Pochi Feb 25 '14 at 05:34
  • Hi, just like the second comment, I ran them all in the same thread (main thread).. NO dispatch_queues. Async dispatch to the main queue is not an issue. NSLog is not use since it never hits there. – Legolas Feb 25 '14 at 05:39
  • try the flush the outpustream of your server to force it send the data immediately – CoolMonster Feb 25 '14 at 05:59
  • As far as I know, queues other than the main queue do not have a run loop attached to them. So I am not sure which run loop you are getting inside your dispatched blocks. If it is the main run loop then the behavior is undefined, since NSRunLoop is not thread safe and its methods should not be called from other threads. Also, the main run loop will already be running and I am unsure what happens if you send it another `run` message. Try commenting out that line and tell us if that helps. – Thorsten Karrer Mar 01 '14 at 11:56
  • Hey guys I am so sorry. This code works fine. It was more of a server side issue. Lol – Legolas Mar 01 '14 at 18:30

1 Answers1

0

Turns out it was a server-side issue. Code is good.

Legolas
  • 12,145
  • 12
  • 79
  • 132