IP Address for Socket Server and Client

I am developing an App using the Networking framework, which can be either a Socket Server or a Socket Client, such that 2 devices can communicate remotely. For the most part I have it working, except:

I am not sure of the best way to determine the IP Address for the Socket Server in order to allow the Client app to connect. I am currently using either of Cloud Functions, or lookup webpages (such as ipify.org) and even reading the IP addresses locally from within the device (this returns many, but not all of them connect successfully). These options seem to work if the Socket Server app is connected to the internet with an IPv6 address, but I find that when the Socket Server app is connected with an IPv4 address, the Client app never successfully connects.

How should I: a) force the Socket Server app to have/use an IPV6 address at all times? or b) allow the Client app to connect successfully via an IPv4 address?

And is there a simple way to know what IP Address the Socket Server is listening from?

Answered by DTS Engineer in 811474022

Right, so achieving these goals is a serious challenge. The problem is that device-to-device connections are often not feasible on the modern Internet. The canonical blocker here is NAT.

Imagine you have two devices, A and B, and they’re both behind a NAT. Each device has a private IP address, for example, something on the 192.168.0.0/16 network. When A makes an outgoing connection, the NAT establishes a mapping between A’s private source IP and port and the NAT’s public IP and port. Prior to A making that connection, this mapping doesn’t exist, so B can’t make an incoming connection to A.

In the case of NAT there are well-known techniques to get around this (see NAT traversal) but those only work in specific circumstances. And NAT is not the only challenge here. These days the Internet is full of middleboxen, and those prevent this sort of device-to-device connection in general. And don’t get me started on proxies |-:

Note The reason why you’re seeing this work in the IPv6 case is that IPv6 has lots of addresses and so doesn’t rely on NAT. However, that’s not a solution in general. Not all networks support IPv6 and, even if they do, these connections can be block by some other middlebox, like a firewall.

As to what you should do, that depends on the nature of your product. Is this a game perchance?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

This question, and the question in your other thread, suggest that you’ve misunderstood how networking works on the modern Internet. Before I suggest a path forward, I’d like to make sure I understand your overall goal.

My reading of your question is that:

  • You’re building an app for Apple platforms.

  • You expect this app to be run by two different users…

  • … on two different devices…

  • … which can be anywhere on the Internet.

  • You want to exchange UDP datagrams between those instances of your app.

Is that correct?

If so, what Apple platforms are you targeting?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn You could be right on the misunderstanding of modern networking. I wrote my first socket code in early 1990s. But for this app I'm keen to use the most up-to-date solution possible.

  • Yes. Apple platforms only.
  • Yes. Two separate users...
  • Yes. Two separate devices...
  • which could be in completely different continents.
  • My app doesn't really justify TCP so I chose UDP (for speed, and because TCP ended up needing an NWProtocolFramer due to it combining multiple messages together.)

Currently I am only targeting iOS.

Right, so achieving these goals is a serious challenge. The problem is that device-to-device connections are often not feasible on the modern Internet. The canonical blocker here is NAT.

Imagine you have two devices, A and B, and they’re both behind a NAT. Each device has a private IP address, for example, something on the 192.168.0.0/16 network. When A makes an outgoing connection, the NAT establishes a mapping between A’s private source IP and port and the NAT’s public IP and port. Prior to A making that connection, this mapping doesn’t exist, so B can’t make an incoming connection to A.

In the case of NAT there are well-known techniques to get around this (see NAT traversal) but those only work in specific circumstances. And NAT is not the only challenge here. These days the Internet is full of middleboxen, and those prevent this sort of device-to-device connection in general. And don’t get me started on proxies |-:

Note The reason why you’re seeing this work in the IPv6 case is that IPv6 has lots of addresses and so doesn’t rely on NAT. However, that’s not a solution in general. Not all networks support IPv6 and, even if they do, these connections can be block by some other middlebox, like a firewall.

As to what you should do, that depends on the nature of your product. Is this a game perchance?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Quinn for the explanation. It all makes sense.

My app is not a game, but in simple terms it requires one user to send a small amount of data to another user (possibly remote), on a regular basis (maybe every 5-10 seconds?). I have a working prototype which uses Google Firebase to transfer this data via "documents" in an online database, but of course this has an associated cost.

My hopes were that a socket (or some other mechanism) could provide this functionality for free. The solution doesn't have to be serverless, but should be as cost free as possible.

Hi Quinn,

I feel you were gently guiding me towards GameKit and the Game Center, so I did some research to see if I could go this route.

The good news is that Game Center does EVERYTHING I need, (Send/receive of data, Push Notifications, find and invite friends, nearby users, etc, etc, etc...).

BUT

My app is not a game.

If I could hide all the Game Center parts, we would be good to go. I know I can change the Notifications, and ViewControllers, but the users will still be forced to have a Game Center account and log into it.

I feel that Game Center is an unnecessary distraction for my users.

Is there an alternative, simply using the Apple Sign In? That would be awesome. Thanks again.

My app is not a game

OK. That’s good to know.

I’m reluctant to recommend using GameKit for something that’s not a game, but I’m not sufficiently experienced with that technology to tell you whether using GameKit for this is viable, or for that matter allowed.

It’d certainly be weird from a user level. Imagine I want to set up this communication channel with another user. Do I ask them for their Game Center handle?

I don’t support GameKit myself, so if you have follow-up questions I recommend that you start a new thread in Graphics & Games > GameKit.


One other API that you might want to explore is CloudKit. In CloudKit you can share records with other users and then use standard CloudKit techniques to learn about changes to those records. This is, for example, the mechanism used by Notes for its shared notes.

This isn’t exactly ‘real time’, but IME it’s fairly fast.

CloudKit is another technology that I don’t support, so I can’t offer detailed help on that front. If you have follow-up questions, start a new thread in App & System Services > iCloud & Data.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks again Quinn. I'll have a look into CloudKit, and see if I can get it working in my App.

I'll feed back to you once In know.

IP Address for Socket Server and Client
 
 
Q