NWConnection get default IP Address

When creating an NWConnectionn on a specific local port, the local IP address also needs to be specified. However there does not seem to be any clean API for discovering what the default NWConnection IP address will be.


In fact getting the main local IP address on macOS or iOS does not seem to be straightforward at all.


I found a workaround which scarily relies on the debug description for a network connection. Is there a better, more robust way, more in line with the Network API ?


import Network
import PlaygroundSupport

class IPHelper {
    static var dummy: NWConnection?
    static func getIPThen(callOnMain: @escaping (NWEndpoint.Host) -> Void ) {
        guard dummy == nil else {
            return
        }
        dummy = NWConnection(host: "255.255.255.255", port: 9000, using:.udp)
        dummy?.stateUpdateHandler = {(newState) in
            switch (newState) {
            case .ready:
                let ip = self.dummy?.currentPath?.localEndpoint?.debugDescription.split(separator: ":").first
                self.dummy?.cancel()
                self.dummy = nil
                DispatchQueue.main.async {
                    callOnMain(NWEndpoint.Host("\(ip ?? "")"))
                }
            default:
                break
            }
            
        }
        dummy?.start(queue: .global())
        
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true

IPHelper.getIPThen { (ip) in
    let address = ip
}
Answered by DTS Engineer in 418454022

In fact getting the main local IP address on macOS or iOS does not seem to be straightforward at all.

That’s because it’s not a simple concept. There really is no such thing as the “main local IP address”. Specifically:

  • You have both IPv4 and IPv6.

  • Even if you fix the protocol family, the correct local address depends on the destination address (because Apple platforms use scoped routing).

  • Even if you fix that, there can be multiple equivalent IP addresses assigned to a given interface.

Unless you’re working in a very constrained environment you really need to let the protocol stack choose the source IP.

Which brings us back to what you’re really trying to do. You wrote:

When creating an

NWConnection
on a specific local port, the local IP address also needs to be specified.

It does? I generally do this:

let params = NWParameters.tcp
params.requiredLocalEndpoint = NWEndpoint.hostPort(host: "0.0.0.0", port: 54321)
let conn = NWConnection(host: "example.com", port: 80, using: params)

The only gotcha is that this assumes IPv4. I’m not sure if there’s a protocol-independent way of setting this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

In fact getting the main local IP address on macOS or iOS does not seem to be straightforward at all.

That’s because it’s not a simple concept. There really is no such thing as the “main local IP address”. Specifically:

  • You have both IPv4 and IPv6.

  • Even if you fix the protocol family, the correct local address depends on the destination address (because Apple platforms use scoped routing).

  • Even if you fix that, there can be multiple equivalent IP addresses assigned to a given interface.

Unless you’re working in a very constrained environment you really need to let the protocol stack choose the source IP.

Which brings us back to what you’re really trying to do. You wrote:

When creating an

NWConnection
on a specific local port, the local IP address also needs to be specified.

It does? I generally do this:

let params = NWParameters.tcp
params.requiredLocalEndpoint = NWEndpoint.hostPort(host: "0.0.0.0", port: 54321)
let conn = NWConnection(host: "example.com", port: 80, using: params)

The only gotcha is that this assumes IPv4. I’m not sure if there’s a protocol-independent way of setting this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks so much Quinn,

Using "0.0.0.0" as the Host for the localEnpoint is just what I needed.

Cheers

Guy

Just to close the loop on this:

I’m not sure if there’s a protocol-independent way of setting this.

It seems that there’s not (r. 62922627).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
NWConnection get default IP Address
 
 
Q