NWListener and NWConnection use the same port

My task is to send a packet to 254.0.0.251 and get a response from another IP but to the same port from which it sent the request. This simple code works great in the simulator:

import UIKit
import Network

class ViewController: UIViewController {
    var  connection: NWConnection?
    var  listener: NWListener?
    let  host: NWEndpoint.Host = "224.0.0.251"
    let  port: NWEndpoint.Port = 5353
    var myport: NWEndpoint.Port = 0
    let  params_out = NWParameters.udp
    let  params_in = NWParameters.udp

    override func viewDidLoad() {
        super.viewDidLoad()

        params_out.allowLocalEndpointReuse = true
        params_in.allowLocalEndpointReuse = true
        connection = NWConnection(host: host, port: port, using: params_out)
        connection?.stateUpdateHandler = onStateDidChange(to:)
        connection?.viabilityUpdateHandler = viabilityUpdateHandler(to:)
        connection?.start(queue: .global())
    }

    func portForEndpoint(_ endpoint: NWEndpoint) -> NWEndpoint.Port? {
        switch endpoint {
        case .hostPort(_, let port):
            return port
        default:
            return nil
        }
    }

    func onStateDidChange(to state: NWConnection.State){
        switch (state) {
        case .preparing:
            print("Connection state: preparing")
        case .ready:
            print("Connection state: ready")
        case .setup:
            print("Connection state: setup")
        case .cancelled:
            print("Connection state: cancelled")
        case .waiting:
            print("Connection state: waiting")
        case .failed:
            print("Connection state: failed")
        default:
            print("Connection an unknown state")
        }
    }

    func viabilityUpdateHandler(to state: Bool){
        if (state) {
            NSLog("Connection is viable")
            myport = portForEndpoint((connection?.currentPath?.localEndpoint)!)!
            print(String(describing: myport))
            server()
        } else {
            NSLog("Connection is not viable")
        }
    }

    func server(){
        do {
            listener = try NWListener(using: params_in, on: myport)
        } catch {
            print("exception upon creating listener")
        }

        listener?.stateUpdateHandler = {(newState) in
            print("server: \(newState)")
            switch newState {
            case .ready:
                print("listener ready")
            default:
                break
            }
        }

        listener?.newConnectionHandler = {(newConnection) in
            newConnection.stateUpdateHandler = {newState in
                print("server1_: \(newState)")
                switch newState {
                case .ready:
                    print("ready")
                    self.receiveMessage(connection: newConnection)
                default:
                    break
                }
            }
            print("Connection")
            newConnection.start(queue: DispatchQueue(label: "newconn"))
        }
        listener?.start(queue: .global())
    }

    func receiveMessage(connection: NWConnection) {
        connection.receiveMessage { (data, context, isComplete, error) in
            if(data?.count ?? 0 > 0){
                print("Connection receiveMessage message: \(String(describing: data!.count))")
            }
            self.receiveMessage(connection: connection)
        }
    }
}

But on iPhone IOS 15.4.1, the error is:

[] nw_path_evaluator_evaluate NECP_CLIENT_ACTION_ADD error [48: Address already in use]

What did I do wrong or not do? Thanks for any help! Alex

Answered by sobr in 713236022

К сожалению решить текущую проблему так и не удалось, даже не смотря на заведенный TSI. Все ответы тех. поддержки свелись к "... А компьютер правильно включили? А фары протирали. А по колесам пинали?"

[] nw_path_evaluator_evaluate NECP_CLIENT_ACTION_ADD error [48: Address already in use]

Yeah, this can happen if the connection is not destroyed properly in the app and it's run over and over in a physical device, like you would during development. To resolve this, do one of the following items:

  1. Cancel or destroy the connection each time you are done testing. Cancel the listener too.

  2. Kill the process and restart it.

  3. If this issue persists then uninstall the app and reinstall it.

Calling cancel on the connection should clear this up.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Added to the beginning of the "server" function:

connection?.cancel()

Removed the app from the iPhone.

rebooted iPhone.

100% error repeatability

Added to the beginning of the "server" function: connection?.cancel()

Sorry, I should have been more clear about what I meant here. Instead of adding it to the start of your program, add it to the end so that it cleans up any bound address on the system.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Accepted Answer

К сожалению решить текущую проблему так и не удалось, даже не смотря на заведенный TSI. Все ответы тех. поддержки свелись к "... А компьютер правильно включили? А фары протирали. А по колесам пинали?"

For anyone following along at home, one reason that you receive the [48: Address already in use] error with NWConnectionGroup is because your app is using a multicast address "224.0.0.251" with the port of 5353, which is already being used on the system by mDNSResponder. Using a port such as 5000 or 9005 would resolve this issue. T

Using Multicast is not the only game in town though. Another option for communicating with other devices on the network is to use a Bonjour service. In this situation, a device would discover the Bonjour service and exchange an NWEndpoint and further information.

NWListener and NWConnection use the same port
 
 
Q