5

This happens on device and not on simulator. I opened my app and connected to server using GCDAsyncSocket. When I press home button, putting the app in background, and then switch back to the app, the socket still connects. No problem here.

But if I actually lock the device then unlock it, even right away, the socket disconnects. The error from - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { delegate method says...

err: Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote peer" UserInfo=0x20051cb0 {NSLocalizedDescription=Socket closed by remote peer}

I've checked with server and there's no code that explicitly destroy a connection. I think it's iOS related thing that kills the connection when app is sent to background. But then, I wonder if it's because the app was sent to background, then why home button doesn't kill the connection but locking the device does?

Is there any way to fix this?

===== Current Progress =====

Seems like there will be no solution for this. For now as a work around. I just reconnect if it disconnects unexpectedly. Will keep this question unanswered in hope for a miracle. ;)

Hlung
  • 13,850
  • 6
  • 71
  • 90

3 Answers3

5

Check Apple's documentation "App States and Multitasking":

Be prepared to handle connection failures in your network-based sockets. The system may tear down socket connections while your app is suspended for any number of reasons. As long as your socket-based code is prepared for other types of network failures, such as a lost signal or network transition, this should not lead to any unusual problems. When your app resumes, if it encounters a failure upon using a socket, simply reestablish the connection.

When you lock the device, iOS may decide to tear down sockets anytime. I have made different experiences, some sockets stay open for a bit of time, but they will be closed sooner or later. You will have to deal with it by catching the "app will move to background"/"app will move to foreground" state change notifications.

A workaround is to declare your app as a VoIP app. This will allow you to keep connections open. However, if your app does not really implement VoIP features and you want to submit it to the app store, you will risk a rejection.

tigloo
  • 644
  • 3
  • 8
  • You can't declare your app as VOIP app if it is not. App will get rejected. – Fahri Azimov Apr 17 '13 at 11:42
  • 2
    Please read my comment to the end before you downvote. It is exactly what I stated. Moreover, there are reasons you want to exploit that behavior (intentionally declare the app as VoIP even if it is not a VoIP app), because it can be very useful for private apps or enterprise distribution, where you are in control of the environment. Last but not least, your answer seems to link to the same information that I supplied. – tigloo Apr 17 '13 at 11:57
  • Read also here on what to write in the Info.plist https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW23 – Massimo Dec 12 '16 at 14:12
0

you need to enable backgrounding on socket: its not necessary to add App provides Voice over IP services key in your info.plist

- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port {

    NSLog(@"Socket Did Connect to Host: %@ Port: %hu", host, port);

    //allow socket to operate when the iOS application has been backgrounded
    [self.socket performBlock:^{
        [self.socket enableBackgroundingOnSocket];
    }];
}
Hashem Aboonajmi
  • 13,077
  • 8
  • 66
  • 75
-1

You should try background execution for your app as described here: When an iOS application goes to the background, are lengthy tasks paused?

Community
  • 1
  • 1
Fahri Azimov
  • 11,470
  • 2
  • 21
  • 29