I'm going to dig this back up because it's directly related to my own questions.
The context:
==
@SuperBidi: [When the connection is gracefully closed by the other side....] I don't receive State changes, but I receive errors on my receive function. I was listening to State changes to handle my connection state but I also have to consider that an error in the receive function means that the connection may be down.
@eskimo: Right. You also have to pay attention to EOF in your receive callback, because most TCP connections close cleanly, and that’s how a clean close is indicated.
So with that in mind, here's what I'm doing and seeing:
I open a connection to a remote, the NWConnection state is .ready
(misc things may happen)
I then receive() to wait for any incoming data.
The remote side gracefully closes the connection (FIN/FIN-ACK)
The receive() callback comes back with an error NWError.posix(.ENODATA) (I assume this is the exact "EOF" @eskimo mentioned)
The NWConnection does not change states. It is still .ready.
What's not clear to me is why it's still considered "ready". It seems like conceptually the concept of "ready" doesn't necessarily mean "connected".
And The key question at this moment is, should the local side do anything, or just sit and wait for the local side to send before ever doing anything with the connection.
Now let's say, my local side wants to send data to the remote. The connection is "ready" so:
I call send(), the callback is called with no error
Simultaneously the NWConnection internally recognizes the connection has been reset ([connection] nw_socket_handle_socket_event [C4:2] Socket SO_ERROR [54: Connection reset by peer])
The NWConnection's state now transitions to .failed.
What I'm left with here is a message that says it got through to the remote before the connection failed, but it didn't.
It seems as if when the ENODATA error is passed into the receive() callback, then the connection should be explicitly cancelled, so the local side knows the connection is not established anymore? But then why doesn't the framework itself do this?
How is this supposed to handled correctly?
Thanks.