NWListener on NWConnection port

I'm struggling to use NWListener and NWConnection on the same port.


I have a simple task requires that I send out a UDP datagram to the broadcast address, and expect to receive replies on the port which sent the datagram. In Blue Sockets, I can create a socket, send out the broadcast message and listen and accept connections on the same socket.


In wireshark the exchange looks like:


10.0.0.123     255.255.255.255     UDP     71          62003 -> 9000 Len=29
10.0.0.202     10.0.0.123          UDP     1060        9000 -> 62003 Len=101

However after hours of experimentation in a swift playground, I am not able to create an NWListener and an NWConnection on the same socket.


Here are the salient pieces of code:

let udpListener = try! NWListener(using: .udp)
... setup and start listener
let broadcast: NWEndpoint.Host = "255.255.255.255"
let portUDP: NWEndpoint.Port = 9000
let localPort : NWEndpoint.Port = udpListener!.port!
let localEndpoint = NWEndpoint.hostPort(host: "10.0.0.123", port: localPort)

let parameters = NWParameters.udp
parameters.requiredLocalEndpoint = localEndpoint

let connection = NWConnection(host: broadcast, port: portUDP, using: parameters)


However creating the NWConnection on the same port as the NWListener gives an error that the port is in use. I've tried the reverse, createing the connection on a known port, closing it and starting a listener immediately affterwards on that same port, but that also results in an error.


How can I implement this very simple protocol using the Network API ? Are there some options I need to set ?


Thanks for any help.

Guy

Accepted Reply

I trawled through the source code to the NW classes on github and discovered the answer


            let parameters = NWParameters.udp
            parameters.allowLocalEndpointReuse = true


Seting this on both NWListener and NWConnection sets the reuse option on the socket.

  • Apologies for digging up an ancient thread, @GeeBee2, but I'm trying to do exactly what you describe, for exactly the same reasons. I need to send a broadcast packet from a specific port. Then, the [third-party] service will, by convention, reply to my broadcast on the port I sent from

    I see all of the above, but for the life of me, I can't get it working myself. Do you happen to have a working code sample you could share?

Add a Comment

Replies

I trawled through the source code to the NW classes on github and discovered the answer


            let parameters = NWParameters.udp
            parameters.allowLocalEndpointReuse = true


Seting this on both NWListener and NWConnection sets the reuse option on the socket.

  • Apologies for digging up an ancient thread, @GeeBee2, but I'm trying to do exactly what you describe, for exactly the same reasons. I need to send a broadcast packet from a specific port. Then, the [third-party] service will, by convention, reply to my broadcast on the port I sent from

    I see all of the above, but for the life of me, I can't get it working myself. Do you happen to have a working code sample you could share?

Add a Comment

[I helped caseyliss via another channel but I thought I’d post this here just for the record.]

I need to send a broadcast packet from a specific port. Then, the [third-party] service will, by convention, reply to my broadcast on the port I sent from I see all of the above

A lot of folks in this situation are trying to implement a service discover protocol. My general advice on that front is to use Bonjour. Doing your own service discovery is a bunch of extra code and results in suboptimal on-the-wire behaviour )-:

However, sometimes you get no choice: You have to implement an existing protocol. In that case…

Network framework is cool but it can’t implement all possible UDP architectures (r. 103252571). I called this out in TN3151, which says:

However, not all UDP communication is that straightforward. UDP also supports multicast, broadcast, and other asymmetric designs. Network framework supports UDP multicast using the NWConnectionGroup class, but that support has limits and, specifically, it does not support UDP broadcast. If you need something that’s not supported by Network framework, use BSD Sockets.

Share and Enjoy

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