views:

1755

answers:

4

I am trying to access 61616 in my iPhone app and the SCReachability code indicates that I have a valid network, but I time out trying to write to 61616. Does anyone know:

A. If the iPhone EDGE/3G network has a limited port range or isn't allowed to connect to this port?

B. How I can check explicitly for access to this port. Here is my "is the network reachable" code (borrowed from Apple's examples), which checks for "foo.bar.com" but doesn't show how to check for "foo.bar.com:61616".

Any help is appreciated!

- (BOOL)isDataSourceAvailable{
static BOOL checkNetwork = YES;
BOOL _isDataSourceAvailable = NO;
if (checkNetwork) { // Since checking the reachability of a host can be expensive, cache the result and perform the reachability check once.
    checkNetwork = NO;

    Boolean success;    
    const char *host_name = "foo.bar.com";

    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name);
    SCNetworkReachabilityFlags flags;
    success = SCNetworkReachabilityGetFlags(reachability, &flags);
    _isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
    CFRelease(reachability);
}
return _isDataSourceAvailable;

}

+1  A: 

If your iPhone is connected over EDGE/Mobile, it might be behind a NAT gateway thus you being unable to contact it. At least that's the case with T-Mobile Germany. The iPhone gets an RFC IP address by T-Mobile (172.16.x.x).

I would test it with the iPhone connected to your local WiFi net and -- if possible -- generally design the app in a way that the iPhone contacts a server and then the server can communicate with the phone.

+2  A: 

This is something that varies a lot from not just carrier to carrier but from contract to contract. For example, here in the UK O2 restrict internet access only to web addresses (presumably ports 80 and 443 but I didn't check) for pay-as-you-go customers but allow more-or-less free access for people on a contract. (I would hope that it's a little more open for iPhone PAYG customers.)

I think the practical upshot of this is that you can't assume access to high ports everywhere in the world.

I'm not sure that there's a simple way to check that a particular port is open, probably your best option is to use a "reasonable" timeout. Of course, there are a number of reasons you might get the timeout so your error would have to be suitable vague.

Stephen Darlington
+5  A: 

The SCNetworkReachability API only checks whether the address can be routed to. Quoting the documentation:

"Reachability" reflects whether a data packet, sent by an application into the network stack, can leave the local computer. Note that reachability does not guarantee that the data packet will actually be received by the host.

This has nothing to do with NAT or port restrictions. Routing is based on addresses - not on ports. So all you can find out (via SCNetworkReachability API) is whether you could (in theory) reach the machine's interface. It does not try to establish a connection on a certain port.

So in order to find out whether that service is reachable you will have to try and test yourself. Preferably when the SCNetworkReachability API tells you that a connection can be established. Just try to connect to the server on port 61616 and see whether you get a connection or a timeout. Proper timeout values and handling is crucial here.

tcurdt
A: 

Are you trying to contact your iPhone from an external machine?

That likely does not work. Usually the GPRS/EDGE/UMTS infrastructure blocks incoming connections. Otherwise a mobile subscriber could be billed for unwanted traffic he did not request. (Imagine someone pinging your iPhone once per second for the next six weeks. You would pay for that...)

Solution is to establish a connection from the mobile device to the remote machine and then let the remote machine use that for traffic.