I'm not native to networking so maybe I'm misunderstanding how endPoint information is gathered.
Device_A is browsing and discovers Device_B or the other way around, it doesn't matter because they will both discover each other and send data to open a connection. Because the Network framework does not resolve ipAddresses, - https://developer.apple.com/forums/thread/129644 when a connection is first made I use either the remoteEndPoint (connection.currentPath?.remoteEndpoint // fe80::9821:7fff:fcea:74c4%awdl0.10059) or the endPoint description (connection.endpoint.debugDescription // myApp (2)._myApp._tcplocal.) as a uniqueID for the connection.
I send the data and some other info across the wire, if successful I then place either endPoint inside an ivar dictionary as the key with another value so that I know which device to map a response to once a device responds back.
Right now I only have 2 devices connected, the issue is when I receive a response from Device_B, I'm actually getting the incorrect endPoint information. For some reason I keep getting the endPoint info from Device_A back. It seems like the same endPoint information is getting sent twice. Once to Device_A and then again to Device_B. This exact same thing occurs on Device_B but in reverse. I'm confused as to why this is happening.
For example Device_A first discovers itself, the remoteEndPoint is *fe80::9821:7fff:fcea:74c4%awdl0.10059*, it sends the data. When Device_A receives its own message, I filter it out using the userId and I see the same endPoint info. But when Device_A discovers Device_B, the remoteEndPoint is *fe80::9821:7fff:fcea:74c4%awdl0.27788*. When I receive a response from Device_B, the endPoint information is showing the first one from Device_A *fe80::9821:7fff:fcea:74c4%awdl0.10059*. The same remoteEndPoint info is duplicated. The same exact thing is happening if I use endpoint.debugDescription. This issue occurs on both devices.
NWBrowser:
browser.browseResultsChangedHandler = { (results, changes) in
for change in changes {
switch change {
case .added(let browseResult):
switch browseResult.endpoint {
case .service(let name, let type,_,_):
let connection = PeerConnection(to: browseResult.endpoint)
// ...
}
PeerConnection:
var connection: NWConnection?
init(to endPoint: NWEndpoint) {
// tcpOptions ...
// params ...
// initialize connection and delegate that sends out data
connection.stateUpdateHandler = { (nwConnectionState) in
case .ready:
self.delegate.sendOutgoing(connection)
}
Send Data:
var dict = [String:String]()
var endPointArr = [String]()
func sendOutgoing(_ connection: NWConnection) {
let endPoint = connection.currentPath?.localEndpoint?.debugDescription
or
let endPoint = connection.currentPath?.remoteEndpoint?.debugDescription
// encode the endPoint and currentUserId with some other info, then send it across the wire, if successful make the endPoint a key inside a dictionary and add it to an array to keep track of what endPoints were received
connection.send(content: encodedData, contentContext: context, isComplete: true, completion: .contentProcessed({ [weak self](error) in {
if let error = error { return }
self?.dict[endPoint] = someUniqueValue
self?.endPointArr.append(endPoint)
}))
}
Receiving a response
connection.receive(minimumIncompleteLength: 1, maximumLength: 65535) { [weak self](data, context, isComplete, error) {
if let err = error { return }
if let data = data, !data.isEmpty {
self?.received(data)
}
}
func received(_ data) {
guard let retrievedData = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? MyModel else { return }
guard let endPoint = retrievedData.endPoint as? String, let userID = retrievedData.userId as? String else { return }
print(endPoint) // fe80::9821:7fff:fcea:74c4%awdl0.10059
if userID == Auth.auth().currentUser?.uid {
dict[endPoint] = nil
return
}
endPointArr.forEach { (endPoint) in
print(endPoint) // prints both fe80::9821:7fff:fcea:74c4%awdl0.10059 and fe80::9821:7fff:fcea:74c4%awdl0.27788
}
// this never runs because the key just got set to nil above because Device_B has the same endPoint info
for (key, value) in dict where key == endpoint {
print("key=\(key) : value=\(value)") // someUniqueValue
// show response that this is a response from whichever device has this endPoint
break
}
}
[1]: https://developer.apple.com/forums/thread/129644
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm using peer-to-peer and I successfully connect one client to another but when I send the echo to the individual connection the receiving client doesn't get a response.
Initial send
let data = NYKeyedArchiver....
let message = NWProtocolWebSocket.Metadata(opcode: .text)
let context = NWConnection.ContentContext(identifier: "send",
metadata: [message])
connection.send(content: data, contentContext: context, isComplete: true, completion: .contentProcessed({ (error) in
if let error = error { return }
print("Sent")
}))
Receive data and send Echo response
func receivedIncoming(connection) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 65535) { (data, context, isComplete, error) in
if let err = error {
print(err) // never gets hit
return
}
if let data = data, !data.isEmpty {
// do something with data
if let color = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor {
// this should only run on the other device once echo is received after 5 secs
self?.view.backgroundColor = color
}
let randomColor = UIColor.random // func create random color
let colorData = randomColor.encode() // func encode color to data
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
connection.send(content: colorData, completion : .idempotent)
// I've also tried
let message = NWProtocolWebSocket.Metadata(opcode: .text)
let context = NWConnection.ContentContext(identifier: "send", metadata: [message])
connection.send(content: colorData, contentContext: context, isComplete: true, completion: .contentProcessed({ (error) in
if let error = error { return }
print("Color data sent") // this always prints
}))
}
} else {
print("data is empty") // never gets hit
}
}
}
NWConnection
weak var delegate: PeerConnectionDelegate?
var connection: NWConnection?
// Outgoing Connection
init(endPoint: NWEndpoint, delegate: PeerConnectionDelegate) {
self.delegate = delegate
let tcpOptions = NWProtocolTCP.Options()
tcpOptions.enableKeepalive = true
tcpOptions.keepaliveIdle = 2
let parameters = NWParameters(tls: nil, tcp: tcpOptions)
parameters.includePeerToPeer = true
parameters.allowLocalEndpointReuse = true
connection = NWConnection(to: endPoint, using: parameters)
startOutgoingConnection()
}
// Incoming Connection
init(connection: NWConnection, delegate: PeerConnectionDelegate) {
self.delegate = delegate
self.connection = connection
startIncomingConnection()
}
func startIncomingConnection() {
connection?.stateUpdateHandler = { (nwConnectionState) in
case .ready:
self.delegate?.receivedIncoming(connection)
// ...
}
Why is the echo data being sent but not received?