Hello,
I'm working with the Network framework in Swift and have encountered an issue when attempting to create multiple NWListener instances on the same port. I am specifically trying to set the allowLocalEndpointReuse property on the NWParameters used for both listeners, but it seems that even with this property set, the second listener fails to start.
Here’s a simplified version of my implementation:
import Foundation
import Network
class UDPServer {
private var listener1: NWListener?
private var listener2: NWListener?
private let port: NWEndpoint.Port
init(port: UInt16) {
self.port = NWEndpoint.Port(rawValue: port) ?? NWEndpoint.Port(45000)
startListeners()
}
private func startListeners() {
let udpOptions = NWProtocolUDP.Options()
let params = NWParameters(udp: udpOptions)
params.allowLocalEndpointReuse = true
// Create first listener
do {
listener1 = try NWListener(using: params, on: port)
listener1?.start(queue: .global())
} catch {
print("Failed to create Listener 1: \(error)")
}
// Create second listener
do {
listener2 = try NWListener(using: params, on: port)
listener2?.start(queue: .global())
} catch {
print("Failed to create Listener 2: \(error)")
}
}
}
// Usage example
let udpServer = UDPServer(port: 45000)
RunLoop.main.run()
Observations:
I expect both listeners to operate without issues since I set allowLocalEndpointReuse to true.
However, when I attempt to start the second listener on the same port, it fails with an error.
output
nw_path_evaluator_evaluate NECP_CLIENT_ACTION_ADD error [48: Address already in use]
nw_path_create_evaluator_for_listener nw_path_evaluator_evaluate failed
nw_listener_start_on_queue [L2] nw_path_create_evaluator_for_listener failed
Listener 1 ready on port 45000
Listener 2 failed: POSIXErrorCode(rawValue: 48): Address already in use
Listener 2 cancelled
Questions:
-
Is there a limitation in the Network framework regarding multiple listeners on the same port even with allowLocalEndpointReuse?
-
Should I be using separate NWParameters for each listener, or is it acceptable to reuse them?
-
Even when trying to initialize NWParameters with NWProtocolUDP.Options, it doesn't seem to change anything. What steps should I take to modify these properties effectively?
-
If I wanted to set the noDelay option for TCP, how would I do that? Even when initializing NWParameters with init(.tls: , .tcp:), it doesn't seem to have any effect.
Any insights or recommendations would be greatly appreciated!
Thank you!
I don’t think that you’re going to be able to make this work. Network framework’s UDP support is rather limited, something I called out in TN3151 Choosing the right networking API. In the specific case of an NWListener
, the UDP use case it supports is kinda like a TCP listener. That is:
-
You listen on a port.
-
When a UDP packet comes in to that port, it spawns an
NWConnection
for that flow, where a flow is defined as a series of datagrams that all have the same local IP / local port / remote IP / remote port tuple.
This model isn’t compatible with multiple listeners, because it’s not obvious which listener would see the flow and then spawn the connection that ends up owning that flow.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"