I have a NWBrowser and a NWConnection on my iPhone 7+ (real device) that sends out some data. On the simulator I have a NWListener and a NWConnection that receives the data.
Inside the NWListener class named PeerListener, inside the listener.newConnectionHandler callback I have a delegate to create a NWConnection that gets hit multiple times when I put a break point on it. This results in the NWConnection's connection.stateUpdateHandler printing out the following multiple times below:
After the last print statement, which is .ready, the connection is sent over to the VC via a delegate where connection.receiveMessage runs. I put a break point on it, it gets hit, but the call back is never entered.
I'm not sure what the problem is because the connection is definitely happening between the device and simulator, all the correct methods are hit (unfortunately multiple times), but the callback is never entered. What is the problem here?
NWListener
VC that initializes the Listener, connection.receiveMessage is in here, last function at the bottom, line 23
NWConnection
Inside the NWListener class named PeerListener, inside the listener.newConnectionHandler callback I have a delegate to create a NWConnection that gets hit multiple times when I put a break point on it. This results in the NWConnection's connection.stateUpdateHandler printing out the following multiple times below:
Code Block // these are all .preparing and .ready cases Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established
After the last print statement, which is .ready, the connection is sent over to the VC via a delegate where connection.receiveMessage runs. I put a break point on it, it gets hit, but the call back is never entered.
I'm not sure what the problem is because the connection is definitely happening between the device and simulator, all the correct methods are hit (unfortunately multiple times), but the callback is never entered. What is the problem here?
NWListener
Code Block protocol PeerListenerDelegate: class { func createNewIncoming(_ connection: NWConnection) } class PeerListener { weak var delegate: PeerListenerDelegate? fileprivate var listener: NWListener? init () { do { let tcpOptions = NWProtocolTCP.Options() tcpOptions.enableKeepalive = true tcpOptions.keepaliveIdle = 2 let parameters = NWParameters(tls: nil, tcp: tcpOptions) parameters.includePeerToPeer = true listener = try NWListener(using: parameters) listener?.service = NWListener.Service(name: "MyName", type: "_myApp._tcp") startListening() } catch let error as NSError { print("Failed to create listener", error.debugDescription) } } fileprivate func startListening() { guard let listener = listener else { return } listener.stateUpdateHandler = { [weak self](newState) in switch newState { case .setup: print("listener setup") case .ready: print("Listener ready on \(String(describing: listener.port))") case .cancelled: print("listener cancelled") case .failed(let error): if error == NWError.dns(DNSServiceErrorType(kDNSServiceErr_DefunctConnection)) { listener.cancel() self?.startListening() } else { print(error.debugDescription) listener.cancel() } default:break } } receivedNewConnectionFrom(listener) listener.start(queue: .main) } fileprivate func receivedNewConnectionFrom(_ listener: NWListener) { listener.newConnectionHandler = { [weak self](newConnection) in self?.delegate?.createNewIncoming(newConnection) } } }
VC that initializes the Listener, connection.receiveMessage is in here, last function at the bottom, line 23
Code Block class ViewController: UIViewController { fileprivate var listener: PeerListener? fileprivate var connectionIncoming: ConnectionIncoming? override func viewDidLoad() { super.viewDidLoad() listener = PeerListener() listener?.delegate = self } // 1. PeerListenerDelegate to create NWConnection object func createNewIncoming(_ connection: NWConnection) { self.connectionIncoming = ConnectionIncoming(connection:connection, delegate: self) } // 2. ConnectionIncomingDelegate to receive data from connection object func receivedIncoming(_ connection: NWConnection) { connection.receiveMessage { [weak self](data, context, isComplete, error) in print(" *** callback entered * THIS NEVER GETS HIT *** ") if let err = error { print("Recieve error: \(err.debugDescription)") return } if isComplete { print("Receive is complete") if let data = data, !data.isEmpty { self?.received(data, from: connection) } } else { print("Not Complete") } } } }
NWConnection
Code Block protocol ConnectionIncomingDelegate: class { func receivedIncoming(_ connection: NWConnection) } class ConnectionIncoming { weak var delegate: ConnectionIncomingDelegate? private var connection: NWConnection? init(connection: NWConnection, delegate: ConnectionIncomingDelegate) { self.delegate = delegate self.connection = connection startConnection() } func startConnection() { guard let connection = connection else { return } connection.stateUpdateHandler = { [weak self](nwConnectionState) in switch nwConnectionState { case .preparing: print("Connection preparing") case .setup: print("Connection setup") case .waiting(let error): print("Connection waiting: ", error.debugDescription) case .ready: print("Connection established") self?.delegate?.receivedIncoming(connection) case .failed(let error): print("Connection failed: ", error.debugDescription) connection.cancel() default:break } } connection.start(queue: .main) } }
I found the answer to my problem here
@eskimo said:
. TCP is not a message-oriented protocol, and thus
doesn’t make any sense [1]. What you want is
And he is 100% correct, as soon as I changed signatures, the callback was entered:
The multiple calls is still happening be that's another question that I'll ask in a different post.
PS I don't know why I have 3 different usernames under the same account
lsamaria is the same person as ohmannnnnn who is the same person as lance145
@eskimo said:
. TCP is not a message-oriented protocol, and thus
Code Block receiveMessage(…)
doesn’t make any sense [1]. What you want is
Code Block receive(minimumIncompleteLength:maximumLength:completion:)
And he is 100% correct, as soon as I changed signatures, the callback was entered:
Code Block connection.receive(minimumIncompleteLength: 1, maximumLength: 8192) { [weak self](data, context, isComplete, error) in print("\n*** call back entered *** ") if let err = error { print("Recieve error: \(err.localizedDescription)") return } print("databytes", data?.count as Any) if let data = data, !data.isEmpty { print("Receive is complete") self?.received(data, from: connection) } }
The multiple calls is still happening be that's another question that I'll ask in a different post.
PS I don't know why I have 3 different usernames under the same account
lsamaria is the same person as ohmannnnnn who is the same person as lance145