Why is GCDAsyncSocket readData only meant to be read once?

One thing I found unintuitive about the GCDAsyncSocket didReadData callback is that it doesn't get called again unless you issue another readData. Why is it designed this way? Is it correct to expect the library user to initiate another read call to receive the callback, or is this a design bug?

eg.

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
     ...
    // initiate the first read
    self.socket = newSocket;
    [self.socket readDataWithTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    // do what you need with the data...

    // read again, or didReadData won't get called!
    [self.socket readDataWithTimeout:-1 tag:0];
}

      

+3


source to share


3 answers


Why is it designed this way?

As long as you are only using the readDataWithTimeout :: tag it might seem more intuitive to just call the delegate method whenever new data comes in.

But readDataWithTimeout: tag: is not the only way to read data using GCDAsyncSocket. There are also, for example, readDataToLength: withTimeout: tag: and readDataToData: withTimeout: tag:



Both of these methods call the delegate at specific points in the input data, and you may want to call different ones at different points in your processing.

For example, if you were handling a stream format where there was a CRLF delimited header followed by a variable length body whose length was provided in the header, then you could alternate between calls to readDataToData: withTimeout: tag: read the header you know. and then readDataToLength: withTimeout: tag: read the body which length you pulled from the header.

+6


source


It is right; you must continue the read loop in the delegate method.



+1


source


Expanding on what Simon Jenkins said:

    - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
    {

        // This method is executed on the socketQueue (not the main thread)
        switch (tag) {
            case CHECK_STAUTS:
                [sock readDataToData:[GCDAsyncSocket ZeroData] withTimeout:READ_TIMEOUT tag:CHECK_STAUTS];
                break;

            default:
                break;
        }


    }



    - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        // This method is executed on the socketQueue (not the main thread)
     dispatch_async(dispatch_get_main_queue(), ^{
            @autoreleasepool {

                if (tag == CHECK_STAUTS) {
    //TODO: parse the msg to find the length.
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

                    [serverSocket readDataToLength:LENGTH_BODY withTimeout:-1 tag:CHECK_STAUTS_BODY]; 

                } else if (tag == CHECK_STAUTS_BODY) {
//TODO: parse the msg to the body content
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
                }

            }
        });


        // Echo message back to client
        //[sock writeData:data withTimeout:-1 tag:ECHO_MSG];
    }

      

0


source







All Articles