Why GCDAsyncSocket always disconnect afters read timeout?
Asked Answered
C

1

5

I looked into GCDAsyncSocket.m at the code that handles read timeout. If I don't extend the timeout, it seems that socket got closed and there is no option to the socket alive keep. I can't use infinite timeout (timeout = -1) because I still need to know when it is timed out, but also doesn't want it to disconnect. I'm not sure there is a reason behind this. Does anyone know?

- (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension
{
    if (currentRead)
    {
        if (timeoutExtension > 0.0)
        {
            currentRead->timeout += timeoutExtension;

            // Reschedule the timer
            dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeoutExtension * NSEC_PER_SEC));
            dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0);

            // Unpause reads, and continue
            flags &= ~kReadsPaused;
            [self doReadData];
        }
        else
        {
            LogVerbose(@"ReadTimeout");

            [self closeWithError:[self readTimeoutError]];
        }
    }
}

FYI, there is a pull request at https://github.com/robbiehanson/CocoaAsyncSocket/pull/126 that adds this keep-alive feature but it is not pulled yet.

Catfish answered 7/2, 2013 at 11:24 Comment(0)
B
14

I am the original author of AsyncSocket, and I can tell you why I did it that way: there are too many ways for protocols to handle timeouts. So I implemented a "hard" timeout and left "soft" timeouts up to the application author.

The usual way to do a "soft" timeout is with an NSTimer or dispatch_after. Set one of those up, and when the timer fires, do whatever you need to do. Meanwhile, use an infinite timeout on the actual readData call. Note that infinite timeouts aren't actually infinite. The OS will still time out after, say, 10 minutes without successfully reading. If you really want to keep the connection alive forever, you might be able to set a socket option.

Brier answered 28/2, 2013 at 18:53 Comment(4)
So to do this, you mean I have call the actual readData with infinite timeout inside the code when my soft timeout NSTimer or dispatch_after fires? Just making sure :)Catfish
No, I meant do the actual readData with an infinite timeout, but at the same time set up the NSTimer or dispatch_after to fire after the soft timeout. But I notice that more recent versions of AsyncSocket (extended and maintained by others) has a delegate call designed to let you do soft timeouts in an easier way.Brier
Ah, thanks for pointing it out. If possible, could you please give me an example of those repo? I did google it but there are a lot out there and their description just looks the same. :/Catfish
nvm, I implemented soft timeout by myself. It's not that hard. After all, I begin to realize that soft timeout is the way socket should work and throw away all my keep-alive codes. Thanks again!Catfish

© 2022 - 2024 — McMap. All rights reserved.