IOS: Networking Basics Using CFStreamCreatePairWithSocketToHost

Usage example

I use sockets to send and receive data using CFStreamCreatePairWithSocketToHost()and try to wrap my head around how this is done when sending multiple data sets (i.e. not only 1 request).

Problem

Currently, I can send data and receive a response (i.e. 1 time in two rounds). However, after sending all the data to the outputStreamstream, it closes (i.e., Accepts NSStreamEventEndEncountered).

Question

So the question is, what happens when I want to send multiple data requests?

  • Do I install a new socket every time I have a new data object to send?
  • I need to reset outputStreamand send more data.

The code

Most of this code is taken from Cocoa Stream Documentation :

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    _data = [[NSMutableData alloc] init];
    [self initNetworkCommunication];

    [self sendString:@"Hello World!"];
}

- (void)initNetworkCommunication {
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"123.456.0.0", 1234, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream; // ivar
    [inputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];

    outputStream = (NSOutputStream *)writeStream; // ivar
    [outputStream setDelegate:self];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream open];
}

- (void)sendString:(NSString *)string {
    NSData *data = [[NSData alloc] initWithData:[string dataUsingEncoding:NSASCIIStringEncoding]];
    [_data appendData:data];
    [data release];
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
    NSLog(@"stream event %u", streamEvent);

    switch (streamEvent) {
        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;
        case NSStreamEventHasSpaceAvailable: {
            uint8_t *readBytes = (uint8_t *)[_data mutableBytes];
            readBytes += byteIndex; // ivar
            int data_len = [_data length];
            unsigned int len = ((data_len - byteIndex >= 1024) ? 1024 : (data_len - byteIndex));
            uint8_t buf[len];
            (void)memcpy(buf, readBytes, len);
            len = [(NSOutputStream *)theStream write:(const uint8_t *)buf maxLength:len];
            NSLog(@"Sending buffer of len: %d", len);
            byteIndex += len;
            break;
        }
        case NSStreamEventHasBytesAvailable:
            if (theStream == 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);
                        }
                    }
                }

                [self sendString:@"Another Test"];
            }
            break;
        case NSStreamEventErrorOccurred:
            NSLog(@"Can not connect to the host!");
            break;
        case NSStreamEventEndEncountered:
            NSLog(@"Closing stream...");
            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [theStream release];
            theStream = nil;
            break;
        default:
            NSLog(@"Unknown event");
    }
}

Answer:

2012-08-15 08:16:30.896 Sockets[34836:f803] Opened input stream.
2012-08-15 08:16:30.898 Sockets[34836:f803] Opened output stream.
2012-08-15 08:16:30.899 Sockets[34836:f803] Sending buffer of len: 12
2012-08-15 08:16:30.900 Sockets[34836:f803] Sending buffer of len: 0
2012-08-15 08:16:30.901 Sockets[34836:f803] Closing output stream.
2012-08-15 08:16:30.939 Sockets[34836:f803] server said: Hello World!

Please note that the stream outputStreamcloses after sending data. I am trying to initialize outputStreamto [self sendString:@"Another Test"];. I also tried idz answer.

In the documentation, I believe that the len: 0 mail buffer is my problem.

If the delegate receives the NSStreamEventHasSpaceAvailable event and writes nothing to the stream, it no longer receives the event-space from the launch loop until the NSOutputStream object receives more bytes. When this happens, the execution loop is restarted for events available in space.

However, the documentation says nothing about closing the stream when the end of the stream is reached. Therefore, I am confused ...

+5
source share
1

, , , . , , . .

API CFStreamCreatePairWithSocketToHost - , . , API , , .

, . . . , .

, ?

. , , , . .

reset outputStream .

, , .

, , len: 0 - .

( 0) . , . , , , . , 0 . . Apple Bug Reporter , .

, , - . , , , -. , , , - , , .

+15

All Articles