How to Activate Tcp Keepalive on Apple iOS Devices

Is it possible to activate TCP keepalive on Apple iOS devices

see: http://en.wikipedia.org/wiki/Keepalive#TCP_keepalive

Usually, keepalive time (net.inet.tcp.keepidle) is 7200sec by default.
I don't know that is true in iOS or not, but "no less than 2 hours" is clearly required by RFC 1122.

This interval MUST be
configurable and MUST default to no less than two hours.

So, how could you configure it in your application? try:

#import <sys/types.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet/tcp.h>

int on = 1;
int delay = 120;
setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
setsockopt(socket_handle, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay));

see man tcp.

I confirmed this works on iOS Simulator (iPhone 5s / iOS 8.0).

How can an iOS app keep a TCP connection alive indefinitely while in the background?

Tapbots solved this problem with Pastebot by prompting the user to run a silent background audio track at all times.

Note that Apple frowns on using hacks like employing the background audio or VOIP APIs to keep non audio or VOIP apps running (as evidenced by the 'workaround' described in the article above) so dabbling with these techniques risks rejection at the point of submission.

Unfortunately, though, there is no legal API to keep a connection alive in the background. Perhaps they'll introduce one in a future update to iOS, but you might consider submitting a feature request to voice your support for it.

Keeping a socket connection alive in iOS

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.

Configuring TCP keepalive after accept

Here is a minimal working example. If it works for you, you can use it as a reference.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#define check(expr) if (!(expr)) { perror(#expr); kill(0, SIGTERM); }

void enable_keepalive(int sock) {
int yes = 1;
check(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(int)) != -1);

int idle = 1;
check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(int)) != -1);

int interval = 1;
check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(int)) != -1);

int maxpkt = 10;
check(setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &maxpkt, sizeof(int)) != -1);
}

int main(int argc, char** argv) {
check(argc == 2);

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(12345);
check(inet_pton(AF_INET, argv[1], &addr.sin_addr) != -1);

int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
check(server != -1);

int yes = 1;
check(setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != -1);

check(bind(server, (struct sockaddr*)&addr, sizeof(addr)) != -1);
check(listen(server, 1) != -1);

if (fork() == 0) {
int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
check(client != -1);
check(connect(client, (struct sockaddr*)&addr, sizeof(addr)) != -1);
printf("connected\n");
pause();
}
else {
int client = accept(server, NULL, NULL);
check(client != -1);
enable_keepalive(client);
printf("accepted\n");
wait(NULL);
}

return 0;
}

Example output (tcpdump reports keepalive packets every second):

$ ./a.out 127.0.0.1 &
[1] 14010
connected
accepted

$ tcpdump -n -c4 -ilo port 12345
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
18:00:35.173892 IP 127.0.0.1.12345 > 127.0.0.1.60998: Flags [.], ack 510307430, win 342, options [nop,nop,TS val 389745775 ecr 389745675], length 0
18:00:35.173903 IP 127.0.0.1.60998 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745775 ecr 389745075], length 0
18:00:36.173886 IP 127.0.0.1.12345 > 127.0.0.1.60998: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745875 ecr 389745775], length 0
18:00:36.173898 IP 127.0.0.1.60998 > 127.0.0.1.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 389745875 ecr 389745075], length 0
4 packets captured
8 packets received by filter
0 packets dropped by kernel


Related Topics



Leave a reply



Submit