Best Way To Determine If Host Is Not Reachable in NWConnection

I have an app that is communicating with a non-HTTP server over TCP/IP. Most everything is working, but I was testing some error conditions and the first one I tried was turning the server off and then trying to send it a message.

I'm using code that uses NWConnection and involves an async method that includes a withCheckedContinuation. Inside this code are checks for errors in the closures, etc. You've seen the example code posted here in the forums. But none of the error code ever gets invoked. I also have a state handler to check the state of the TCP connection.

What I see when I send the request is:

  1. connection goes to .preparing state
  2. nothing happens for about 45 seconds
  3. I then get two errors:

inline-code nw_endpoint_flow_failed_with_error [C4.1.1 192.168.86.44:3040 in_progress channel-flow (satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, dns, uses wifi)] already failing, returning inline-code nw_endpoint_flow_failed_with_error [C4.1.1 192.168.86.44:3040 cancelled channel-flow ((null))] already failing, returning

  1. then the connection state goes to .waiting

and nothing else happens. I would really like to capture the errors I see in the Xcode console, but I don't know how to catch them. Anyone have any ideas? Is there a better way to send the first message (or a ping or whatever) to a non-HTTP server and see if it is there?

Thanks, Robert

Answered by DTS Engineer in 826054022

Network framework, being a relatively low-level API, tends not to apply its own policy to retries, timeouts, and so on. Instead you get the default policies from the underlying protocol, TCP in this case.

There’s a lot of general lore about how to manage a TCP connection correctly. Much of that isn’t specific to Network framework. For example, if you read a book about BSD Sockets and it says that you need to enable keepalives to ‘garbage collect’ TCP connections that have been zombified by an intervening NAT, you need to map the BSD Sockets constructs (the SO_KEEPALIVE socket option and its friends) to Network frameworks constructs (the enableKeepalive and its friends).

However, there are some cases where Network framework is unique, and this is one of them:

Written by robertlnielsen in 774933021
I would really like to capture the errors

There’s no way to capture that specific text, but if the connection goes into in the .waiting(_:) state then you can get the error from the associated NWError value.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Network framework, being a relatively low-level API, tends not to apply its own policy to retries, timeouts, and so on. Instead you get the default policies from the underlying protocol, TCP in this case.

There’s a lot of general lore about how to manage a TCP connection correctly. Much of that isn’t specific to Network framework. For example, if you read a book about BSD Sockets and it says that you need to enable keepalives to ‘garbage collect’ TCP connections that have been zombified by an intervening NAT, you need to map the BSD Sockets constructs (the SO_KEEPALIVE socket option and its friends) to Network frameworks constructs (the enableKeepalive and its friends).

However, there are some cases where Network framework is unique, and this is one of them:

Written by robertlnielsen in 774933021
I would really like to capture the errors

There’s no way to capture that specific text, but if the connection goes into in the .waiting(_:) state then you can get the error from the associated NWError value.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Fair enough on the timeout, Quinn. I was really trying to just determine if the connection was going to work at all, or was destined to fail. Looking for the error on the .waiting state works.

But I have two additional questions:

  1. Should I specifically look for NWError? Or should I look for POSIXError? Or just plain error?

  2. Is there somewhere I can read how to do this without asking on the forum? Is there a record of the "lore" as it pertains to the Network Framework that I can study?

Thanks again for the help! Robert

Written by robertlnielsen in 826086022
Should I specifically look for NWError?

Well, that associated value for the .waiting(_:) state is an NWError, so you can’t avoid looking at that (-:

NWError itself is an enum with cases for each of the known sources of error, currently .posix(_:), .dns(_:), and .tls(_:).

Written by robertlnielsen in 826086022
Is there a record of the "lore" as it pertains to the Network Framework that I can study?

I’m not aware of such a thing. Usually folks find this stuff because they know what BSD Sockets would use and it’s relatively easy to search for the corresponding terms in Network framework. However, I’m not aware of any summary of that mapping.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Best Way To Determine If Host Is Not Reachable in NWConnection
 
 
Q