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

e.g.

- (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];
}
有帮助吗?

解决方案

Why is it designed that way?

As long as you're only ever using readDataWithTimeout:tag: it may seem more intuitive to just have the delegate method called whenever some new data has arrived.

But readDataWithTimeout:tag: isn't the the only way to read data with GCDAsyncSocket. There are also e.g. readDataToLength:withTimeout:tag: and readDataToData:withTimeout:tag:

Both of these methods call the delegate at specific points in the incoming data, and you might 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 might want to alternate between calls of readDataToData:withTimeout:tag: to read the header whose delimiter you know, and then readDataToLength:withTimeout:tag: to read the body whose length you have pulled from the header.

其他提示

That is correct; you are expected to continue the read loop in the delegate method.

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];
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top