Hello,
I'd like to find an available TCP port. I came up with this code:
#!/usr/bin/env swift
import Foundation
import Network
func findAvailablePort() -> UInt16 {
let semaphore = DispatchSemaphore(value: 0)
let listener = try! NWListener(using: .tcp, on: .any)
listener.stateUpdateHandler = { state in
switch state {
case .ready:
semaphore.signal()
case .failed(let e):
fatalError(e.localizedDescription)
default:
break
}
}
listener.newConnectionHandler = { conn in }
listener.start(queue: .global())
let timeout = DispatchTime.now() + DispatchTimeInterval.seconds(5)
if semaphore.wait(timeout: timeout) == .timedOut {
fatalError("timeout")
}
return listener.port!.rawValue
}
print(findAvailablePort())
Any feedback, especially around error handling, would be very appreciated. (The two error conditions I've identified, network error and semaphore timeout, seem unlikely to hit so I reached for fatalError.)
To give some more context, I'm writing an application with processes A and B. A starts B via Process()
. B will listen on a TCP socket but A needs to know which one. (I'd rather not use stdio to let it know.) So A will find a free tcp port, start B, and pass port in argv. There's obviously a possible race condition between finding the free port and listening on it but it seems unlikely to hit given the OS doesn't seem to "recycle" free ports right away.