输入流调用事件NSStreamEventHasBytesAvailable,但该流不包含任何字节

时间:2017-03-08 19:33:52

标签: ios objective-c sockets

如果在服务器上发生短暂延迟后发送数据,则输入流工作正常。仅当服务器在收到数据后立即做出响应时才会出现问题。我在同一个类中处理输入和输出流。

创建流:

// STREAMS
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;

// CREATE READABLE/WRITABLE STREAMS TO HOST/PORT
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)terminalIp, [terminalPort intValue], &readStream, &writeStream);

// SET STREAMS
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;

// SETTING DELEGATES
[inputStream setDelegate:self];
[outputStream setDelegate:self];

// SET LOOP TO LISTEN FOR MESSAGES
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

// OPEN STREAMS
[inputStream open];
[outputStream open];

Stream Delegate事件处理程序:

////////////////////////////////////
// FUNCTION - STREAM EVENT HANDLER
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{

// LOG
if(aStream == outputStream){

    NSLog(@"Status of outputStream: %lu", (unsigned long)[outputStream streamStatus]);

}else{

    NSLog(@"Status of inputStream: %lu", (unsigned long)[inputStream streamStatus]);

}

//
// CHECK EVENTS
//

if(eventCode == NSStreamEventOpenCompleted){

    //
    // STREAM OPEN
    //


}else if(eventCode == NSStreamEventHasBytesAvailable){

    //
    // SERVER SENT BYTES
    //

    // CHECK STREAM TYPE
    if(aStream == inputStream){

        // SETTINGS
        uint8_t buffer[1024];

        // LOOP WHILE THERE ARE BYTES BEING RECIVED
        while ([inputStream hasBytesAvailable]){

            // MAKE SURE THERE ARE BYTES
            if([inputStream read:buffer maxLength:sizeof(buffer)] > 0){

                // SET HEX RESPONSE
                hexResponse = [[NSData alloc] initWithBytes:buffer length:[inputStream read:buffer maxLength:sizeof(buffer)]];

                NSLog(@"hex in stream: %@",hexResponse);

                NSString *incomingString;

                if (hexResponse.length >= 2){


                    // TURN HEX INTO STRING
                    incomingString = [[NSString alloc] initWithData:hexResponse encoding:NSUTF8StringEncoding];
                    NSLog(@"%@", incomingString);

                }


                // MAKE SURE THERE IS TEXT THERE
                if(incomingString.length > 3){

                    // SET TEXT
                    stringResponse = incomingString;

                }

            }

        }

    }

}else if(eventCode == NSStreamEventErrorOccurred){

    //
    // COULDN'T CONNECT
    //

    NSError *theError = [aStream streamError];

    NSLog(@"Stream Error (%ld): %@",(long)[theError code],[theError localizedDescription]);


}else if(eventCode == NSStreamEventEndEncountered){

    //
    // END
    //

    // CHECK STREAM TYPE
    if(aStream == outputStream){

        NSData *newData = [outputStream propertyForKey:
                           NSStreamDataWrittenToMemoryStreamKey];
        if (!newData) {
            NSLog(@"No data written to memory from output stream!");
        } else {
            //[self processData:newData];
            // CONVERT
            //[self translateResponse];
        }
        [outputStream close];
        [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                          forMode:NSDefaultRunLoopMode];

        outputStream = nil;





    }else if(aStream == inputStream){

        NSData *newData = [inputStream propertyForKey:
                           NSStreamDataWrittenToMemoryStreamKey];
        if (!newData) {
            NSLog(@"No data written to memory from input stream!");
        } else {
            NSLog(@"Data found in input stream!");

            //[self processData:newData];
            // CONVERT
            [self translateResponse];
        }
        [inputStream close];
        [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                                forMode:NSDefaultRunLoopMode];

        inputStream = nil;

    }


}else if(eventCode == NSStreamEventHasSpaceAvailable){

    //
    // HAS SPACE TO SEND
    //

    if(aStream == outputStream){
    NSMutableData * dataToSend = [NSMutableData dataWithData:hexRequest];

        uint8_t *readBytes = (uint8_t *)[dataToSend mutableBytes];
        readBytes += byteIndex; // instance variable to move pointer
        NSUInteger data_len = [dataToSend length];
        unsigned long len = ((data_len - byteIndex >= 1024) ?
                            1024 : (data_len-byteIndex));
        uint8_t buf[len];
        (void)memcpy(buf, readBytes, len);
        len = [outputStream write:(const uint8_t *)buf maxLength:len];
        byteIndex += len;

    }


}else{

    //
    // UNKNOWN EVENT
    //

}

} // END FUNCTION

1 个答案:

答案 0 :(得分:0)

问题是由读取输入缓冲区两次引起的。我在条件声明中以及在分配它时阅读它。通过首先分配问题来解决问题。

新守则:

}else if(eventCode == NSStreamEventHasBytesAvailable){

    //
    // SERVER SENT BYTES
    //

    // CHECK STREAM
    if(aStream == inputStream){

        // SSET BUFFER
        uint8_t buffer[1024];

        // LOOP WHILE THERE ARE BYTES BEING RECIVED
        while ([(NSInputStream *)aStream hasBytesAvailable]){

            // READ BUFFER
            hexResponse = [[NSData alloc] initWithBytes:buffer length:[(NSInputStream *)aStream read:buffer maxLength:sizeof(buffer)]];

            // MAKE SURE THERE IS DATA
            if([hexResponse length] > 0){

                // INIT INCOMING STRING
                NSString *incomingString;

                // MAKE SURE RESPONSE IS NOT A HEARTBEAT
                if (hexResponse.length >= 2){

                    // TURN HEX INTO STRING
                    incomingString = [[NSString alloc] initWithData:hexResponse encoding:NSUTF8StringEncoding];
                    NSLog(@"%@", incomingString);

                }


                // MAKE SURE INCOMING STRING IS VALID
                if(incomingString.length > 3){

                    // SET TEXT
                    stringResponse = incomingString;

                }

            }

        }

    }

}