Bonjour NWListener with changing domain name

Hi! I have to say I'm not experienced with network programming. Meanwhile, I'm happy my macOs app is doing mostly what it should with Network framework.

What I noticed though is that, observing with DNS-SD, all other Bonjour Services on my system show the domain name "Felixs-iMac.local" whereas my app has something like c0d52654-4459-4373-a42d-778805c5107a.local with the string before .local changing on each run.

I also noticed that the third party app that I connect my app to locally is not "remembering" my app after restarting. I can set manually "Remote Address" in that app to localhost or 127.0.0.1 and it reconnects next time.

I wonder if this is related.

How can I have my listener show up with a persitent host/domain name (not sure with terminology here..) so other apps can re-connect?

Here's my code for the listener:

// advertise Bonjour
        let udpOption = NWProtocolUDP.Options()
        let params = NWParameters(dtls: nil, udp: udpOption)
        if bonjour { params.includePeerToPeer = true }

        // create the listener
        listener = try! NWListener(using: params, on: 9001)

        // Bonjour service
        if bonjour { listener?.service = NWListener.Service(name: "ControlPilot", type: "_osc._udp", domain: nil, txtRecord: nil)
        }

Replies

I’ve no idea where that UUID is coming from. The general rule with Bonjour service names is:

  • If you supply nil to the name, the system chooses an appropriate name. On the Mac this means the name set in System Preferences > Sharing.

  • If you supply a name yourself, it uses that.

  • Bonjour then auto renames to resolve collisions (unless you opt out of that)

I took the code you posted, added it to a small test app, and tweaked it to compile and run (my code is pasted in below). It works just fine for me. Specifically, once I start the service I see this:

% dns-sd -B _osc._udp. local.
Browsing for _osc._udp..local.
DATE: ---Fri 11 Feb 2022---
10:27:02.174  ...STARTING...
Timestamp     A/R  Flags  if Domain  Service Type Instance Name
10:27:02.175  Add      3   1 local.  _osc._udp.   Slimey
10:27:02.175  Add      3  25 local.  _osc._udp.   Slimey
10:27:02.175  Add      3  27 local.  _osc._udp.   Slimey
10:27:02.175  Add      2   6 local.  _osc._udp.   Slimey
^C 

where Slimey is my Mac’s name. This is running 12.2 with Xcode 13.2.1.

Share and Enjoy

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

import Cocoa
import Network

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    … stuff to set up the UI to call `start()` and `stop()`…

    var listenerQ: NWListener? = nil
    
    func start() {
        let udpOption = NWProtocolUDP.Options()
        let params = NWParameters(dtls: nil, udp: udpOption)

        // create the listener
        let listener = try! NWListener(using: params, on: 9001)
        self.listenerQ = listener

        // Bonjour service
        listener.service = NWListener.Service(name: nil, type: "_osc._udp", domain: nil, txtRecord: nil)
        listener.stateUpdateHandler = { newState in
            print("state did change, state: \(newState)")
        }
        listener.newConnectionHandler = { conn in
            print("did ignore new connection")
        }
        
        listener.start(queue: .main)
    }
    
    func stop() {
        self.listenerQ?.cancel()
        self.listenerQ = nil
    }
}

Hi Quinn, thanks to you, I found the solution:

I had to delete

params.includePeerToPeer = true

and now it works as I wanted! I don't know why I thought to need this bit.

Thanks a lot for the quick help!

btw, I'm on macOs 10.15.7, XCode 12.4