Getting four accepts for a single incoming connection request


Hi, I've constructed a NWListener closely based on the example provided here: https://developer.apple.com/forums/thread/653925?login=true&page=1#621284022
The problem is that the example specifically only handles a single connection request and then ignores all others. I've removed that logic. The problem is that for
code running on two simulators (tvOS and iOS) I get four accepts each time I connect from the client. They are coming in pairs of ipv4/ipv6. The second address might be the simulator,
  1. .0.5 is the mac. I need to implement a server that accepts as many connections over time as needed. My questions are

a) can I only listen on one protocol, for example ipv6 only?
b) if not how should I ignore the other connection? I don't seem to get information into newConnectionHandler, which is too late.
c) why am I getting a second pair of connections?
Thanks in advance for your help!
Cliff

Code Block
func startListener() {
do {
let tcpOption = NWProtocolTCP.Options()
tcpOption.enableKeepalive = true
tcpOption.keepaliveIdle = 2
let params = NWParameters(tls: nil, tcp: tcpOption)
params.includePeerToPeer = true
let listener = try NWListener(using: params)
networkListener = listener
listener.service = NWListener.Service(name: NetworkConstants.serviceName, type: NetworkConstants.serviceType)
listener.newConnectionLimit = NWListener.InfiniteConnectionLimit
listener.stateUpdateHandler = { [weak self] newState in
guard let strongSelf = self else { return }
switch newState {
case .ready:
let listenerMessage = "listening on \(NetworkConstants.serviceName) \(NetworkConstants.serviceType) \(String(describing: strongSelf.networkListener!.port))"
strongSelf.networkDelegate?.didReceiveListenerUpdate(listener: strongSelf, didUpdateMessage: listenerMessage)
case .failed(let error):
strongSelf.networkListener?.cancel()
if strongSelf.didListenerFail {
print("listener did fail")
strongSelf.didListenerFail = true
NetworkListener.shared.startListener()
} else {
let errorMessage = "Listener - failed with \(error.localizedDescription), restarting"
strongSelf.networkDelegate?.didReceiveListenerUpdate(listener: strongSelf, didUpdateMessage: errorMessage)
}
default:
print("listener: unhandled state \(newState)")
break
}
}
listener.newConnectionHandler = { [weak self] newConnection in
guard let strongSelf = self else { return }
strongSelf.networkDelegate?.didReceiveListenerUpdate(listener: strongSelf, didUpdateMessage: "Listener received a new connection")
strongSelf.networkDelegate?.didReceiveNewConnection(listener: strongSelf, newConnection: newConnection)
}
listener.start(queue: .main)
} catch {
print("Can't make listener: \(error.localizedDescription)")
}
}


listener: ScreenshotServer.NetworkListener: Listener received a new connection

listener: ScreenshotServer.NetworkListener: new connection [C1 ::1.52396 tcp, local: ::1.52309, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]
listener: ScreenshotServer.NetworkListener: Listener received a new connection

listener: ScreenshotServer.NetworkListener: new connection [C2 192.168.0.5:52397 tcp, local: 192.168.0.5:52309, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]
listener: ScreenshotServer.NetworkListener: Listener received a new connection

listener: ScreenshotServer.NetworkListener: new connection [C3 192.168.0.2:52398 tcp, local: 192.168.0.2:52309, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]
listener: ScreenshotServer.NetworkListener: Listener received a new connection

listener: ScreenshotServer.NetworkListener: new connection [C4 169.254.240.25:52399 tcp, local: 169.254.240.25:52309, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]

The second address might be the simulator

The iOS Simulator uses the host Mac’s networking stack and thus won’t get its own IP addresses.

Can you explain more about your network setup? Specifically:
  • Where are you running the server?

  • Where are you running the client?

  • How are these devices connected?

  • What API are you using for the client?

  • What IP addresses are assigned to each?

On the Mac you can get a list of IP addresses and their associated interfaces using ifconfig (if you’re having problems mapping BSD interface names to user-visible runs, run networksetup with the -listallhardwareports arguments). On iOS you can get this info from Settings > Wi-Fi.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Hi Quinn, thanks for your quick reply. I realize that I have not mentioned that I'm running xCode 12 and iOS/tvOS 14.

Where are you running the server?
Where are you running the client?

Both are simulators running on my Mac, server is an iOS app and client is tvOS

How are these devices connected?

They are both running in simulators, the server console is visibile in xCode. The client is started by hand in the tvOS simulator.
  • * What API are you using for the client

Given these constants:

Code Block
enum NetworkConstants {
static let serviceDomain = "local."
static let serviceType = "_screenshotCliff._tcp"
static let serviceName = "bongo"
}


The client connects like this (simplified):

Code Block
let connection = NWConnection(to: .service(name: NetworkConstants.serviceName, type: NetworkConstants.serviceType, domain: NetworkConstants.serviceDomain, interface: nil), using: .tcp)
let client = NetworkConnection(newConnection: connection)
connection?.start(queue: .main)


What IP addresses are assigned to each?

The machine has wireless and ethernet, with the ether on en1

en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=400<CHANNELIO>
ether b8:09:8a:cf:fe:3d
inet6 fe80::18c2:7210:652d:f98a%en1 prefixlen 64 secured scopeid 0x5
inet 192.168.0.5 netmask 0xffffff00 broadcast 192.168.0.255

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=50b<RXCSUM,TXCSUM,VLAN
HWTAGGING,AV,CHANNEL_IO>
ether ac:87:a3:1e:9c:22
inet6 fe80::1c86:f135:6ec:1763%en0 prefixlen 64 secured scopeid 0x4
inet 192.168.0.2 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (1000baseT <full-duplex,flow-control,energy-efficient-ethernet>)
status: active

Networksetup sez:
Hardware Port: Ethernet
Device: en0
Ethernet Address: ac:87:a3:1e:9c:22

Hardware Port: Wi-Fi
Device: en1
Ethernet Address: b8:09:8a:cf:fe:3d

So it looks like the client is trying to connect on all four possible paths. Sorry for not mentioning the ethernet, I forgot that it is attached :-)

So it looks like the client is trying to connect on all four possible paths.

Indeed. Apple’s connect-by-name API uses a fancy algorithm to run multiple connections in parallel to see which one connects first (see RFC 8305 for some background on this). It’s possible that this is being tripped up by the loopback connection.

If you accept all four connections, do three of them drop immediately?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Thank you, the other three connections do indeed drop immediately. Now that I know this is normal I can move on :-)
Thanks again

Getting four accepts for a single incoming connection request
 
 
Q