Relying on transport layer behaviour to determine what happened "higher up" is never a good idea. Because the OSI layer model was designed with layer independence in mind, there doesn't have to be a causal relationship between something the user did or did not do and what happens at the transport layer. The only scenario that I can think of where one could theoretically (still unreliable) deduce that the user caused the application to end "normally" would be in the case of a full 4-way connection tear down. This really only happens if nothing goes wrong in any of the layers, which implies that they also give some effort to follow the specification (which SFML already fails to do with its sf::TcpSockets
).
In the hypothetical case where you would punish players if you did detect a 4-way tear down, don't you think it would be unfair to punish the only players who did "behave" and closed the game properly? You would be implicitly rewarding players who worked around the system by e.g. unplugging their network cable.
I think it is kind of obvious that this isn't an easy problem to solve, and adding a few more status codes to sf::Socket definitely won't help either. If you take any of the AAA game developers as an example, they don't differentiate between a temporary power outage or someone who purposely cut their network cable in 2 pieces. What a good game
should do, is provide players a way to recover from such situations by reconnecting within a given time period. People will have much less to complain about if they get a chance to demonstrate their good will (and bad luck) as opposed to instantly being penalized for something unintentional that they could not prevent.
But at the end of the day there is always the one true way of solving this problem: Design your game in a way that rewards people for staying until the end.