Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping a socket connection alive in iOS

I have the following code written in Objective-C that writes data to a socket. The server is running node.js on top of Ubuntu:

NSString *url = @"anIPAddress";        
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;            
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)url, 9000, &readStream, &writeStream);
self.inputStream = (NSInputStream *)readStream;            
self.outputStream = (NSOutputStream *)writeStream;
[self.inputStream setDelegate:self];            
[self.outputStream setDelegate:self];            
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];            
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];            
[self.inputStream open];            
[self.outputStream open];

I am able to connect to the server and send information. However I noticed the connection times out after a few minutes (I think 5 minutes or so?). How can I keep this connection alive? I know there is a disconnect because the same thing happens if I connect to the server under Terminal, I have to keep that connection alive. I imagine the same thing is happening in my code. Thanks for your help!

like image 368
Hahnemann Avatar asked Jul 08 '12 23:07

Hahnemann


2 Answers

The simplest answer is to try to use the SO_KEEPALIVE socket option.

Broken connections can be hard to detect without data flowing between the end-points which is what makes this option in some ways useless as it doesn't use data to detect broken connections. However, it is easy to add to your code to see. Add it and see if it helps...

This is how it's done in C or C++

int opt = 1;
// Get the native socket handle from your socket class here...
int socket_handle = getNativeSocketHandle( self.outputStream );

/*Enabling keep alive*/
if( setsockopt( socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof( opt ) ) < 0 )
{
   // failed setting socket option
}

The not-so-simple answer is to add a ping packet to your protocol and send that ping packet regularly so you can detect a broken connection.

like image 138
JimR Avatar answered Oct 02 '22 20:10

JimR


I found how to do this. Since the server is running node.js, I used

socket.setKeepAlive(true, 2000);

And in this way node keeps each socket open. The default is false, so this is why it was timing out. I hope this is useful to other people. Thank your for your responses, I think keeping a heartbeat (keep-alive) is also a good idea, but with this native approach node takes care of it.

like image 22
Hahnemann Avatar answered Oct 02 '22 22:10

Hahnemann