views:

1321

answers:

5

I've inherited a iPhone application/project that opens a socket connection to another device (think web cam). This works fine as long as the device is reachable over the wifi network. However, if it isn't reachable, the application hangs calling "connect".

(Error checking stripped out for clarity.)

-(void)connect_to_control:(NSTimer*) timer

{

clientsock_fd = socket(AF_INET, SOCK_STREAM, 0);
int no_delay = 1;
setsockopt(clientsock_fd, IPPROTO_TCP, TCP_NODELAY, &no_delay, 4);

struct sockaddr_in the_addr;
memset((void *)&the_addr, 0, sizeof(the_addr));
the_addr.sin_family = AF_INET;
the_addr.sin_port = htons(25556);
const char* server_addr = "192.168.3.22";
unsigned long ip_addr = inet_addr(server_addr);


the_addr.sin_addr.s_addr = ip_addr;
int err_test = connect(clientsock_fd, (const struct sockaddr*)&the_addr, sizeof(the_addr));

}

My first thought was to "ping" the address to see if it is reachable. So far I've discovered Apples "Reachability" sample but that does NOT determine if an address is reachable, only if the network is reachable (except in the simulator) and an old Apple sample "SimplePing" which uses header files that aren't included in the iPhone SDK.

I've got decades of C++/C# experience but I'm an iPhone noob trying to help out a friend's little company debug some stuff in time for an important trade show. Thanks in advance.

+3  A: 

See this question to learn how to put a socket into non-blocking mode.

This is probably what you want to do, as a host may respond to pings even though it's not listening on a particular socket, and vice-versa.

Adam Liss
That answer doesn't really provide the full details of how to do it.
corydoras
+1  A: 

Firstly put the socket into non blocking mode, this means a connect will always return straight away:

lags = fcntl(sock,F_GETFL,0);
fcntl(sock,F_SETFL, flags | O_NONBLOCK)

Then you use the select statement with a timeout value to check if the connection has succeded yet:

select(FD_SETSIZE,0,&wset,0,&timeout)

You can find full explanation of non blocking sockets here

Jacob
OP here: Thanks, this looks promising. I'm trying it this morning.
Chris Bennet
A: 

For whatever reason, I was not able to get a non blocking solution using "select" working. (But thank you both for your helpful responses.) I ended up using one of the socket options that let me specify a shorter timeout.

setsockopt(clientsock_fd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &timeout, sizeof(timeout));

In the interest of completeness, this is what I ended up with (error checking removed for clarity):

-(void)connect_to_control:(NSTimer*) timer

{

clientsock_fd = socket(AF_INET, SOCK_STREAM, 0);
int no_delay = 1;
int result = setsockopt(clientsock_fd, IPPROTO_TCP, TCP_NODELAY, &no_delay, 4);

// *** Set timeout value to stop hanging ***
struct timeval timeout; 
timeout.tv_sec =1;
timeout.tv_usec =0; 
result = setsockopt(clientsock_fd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &timeout, sizeof(timeout));

struct sockaddr_in the_addr;
memset((void *)&the_addr, 0, sizeof(the_addr));
the_addr.sin_family = AF_INET;
the_addr.sin_port = htons(25556);
const char* server_addr = "192.168.3.22";
unsigned long ip_addr = inet_addr(server_addr);
the_addr.sin_addr.s_addr = ip_addr;

int err_test = connect(clientsock_fd, (const struct sockaddr*)&the_addr, sizeof(the_addr)); // hangs here when address can't be reached!

NOTE: I had to upgrade to OS 3.0 to use TCP_CONNECTIONTIMEOUT. TCP_CONNECTIONTIMEOUT is defined in "tcp.h" the OS 3.0 SDK headers but not in OS 2.1. It is not defined in the simulator headers, only the device headers.

Chris Bennet
A: 

is it working that solution!?? First of all TCP_CONNECTIONTIMEOUT is wrong and it should be SO_RCVTIMEO, but anyway, it freeze anyway... I have the same problems and cannot find the solution... :((

Plase, can anybody hel me?

What OS are you using? TCP_CONNECTIONTIMEOUT is only available in iPhone OS 3.0, on the device, not the simulator.
Chris Bennet
yes, you are right; in simulator it's not available. Thanks. I will try if it works properly.
A: 

Hi Chris I'm trying to make a TCP connection like you describe but I don't understand how I send and get messages through this socket. Any help will be good Thanks Gilad

gkedmi