"What could possibly go wrong with using UDP for inter-process communications on a single Windows PC?" I thought... and proceeded to implement it.
But despite sending mere hundreds of bytes and only very sporadically, and also despite UDP being used as a connectionless protocol (sendto()
function employed), I am plagued by random occurrences of error 10054 - "connection reset". I find this very confusing. Is it:
- perfectly normal, to be expected, in which case... what does it mean has happened?
- completely unexpected, and I've probably implemented something wrong
- completely unexpected, so I should check for conflicting software (e.g. for problems like this)
- something else?
I read somewhere that it could indicate that there is no receiving port open at the other end... but this makes even less sense to me - isn't UDP simply supposed to send the datagram off and not care what happens to it? Or is there some special case when the send occurs to/from ports on the same machine (localhost)?
In my specific case, I had a server running on localhost listening on a UDP socket bound to a specific port. It also had a second UDP socket bound to the same port (it makes sense in context), used only for sending responses to the packets received on the first socket.
Clients, also running on localhost, would create a temporary socket, send a packet to the server, wait for a response, then close their socket. The timeout on the client side was very short (for application-specific reasons), with a retry if the initial attempt timed out.
What would happen on occasion is a client would send a packet to the server, time out before the response could be sent, and close its socket. The server would then receive (on the listening socket) the packet from the client, and send back a response (on the sending socket). However, Windows "helpfully" sends back an ICMP response stating that there's no longer any socket listening on the destination port. Crucially, this packet ends up being delivered to the listening socket, and not to the sending socket (since they both share the same port). On the next read from the listening socket on the server receives a
WSAECONNRESET
error indicating the previous packet it sent (which was actually sent from a different socket) failed to get delivered.In my case, the fix was simply to ignore
WSAECONNRESET
errors on the listening socket. The listening socket continued to successfully receive other packets after such errors occurred, and the sending socket continued to successfully send packets after a packet failed to get delivered.