问题
I created a simple persistent socket connection for our game using TcpClient
and NetworkStream
. There's no problem connecting, sending messages, and disconnecting normally (quitting app/server shuts down/etc).
However, I'm having some problems where, in certain cases, the client isn't detecting a disconnection from the server. The easiest way I have of testing this is to pull out the network cable on the wifi box, or set the phone to airplane mode, but it's happened in the middle of a game on what should otherwise be a stable wifi.
Going through the docs for NetworkStream
etc, it says that the only way to detect a disconnection is to try to write to the socket. Fair enough, except, when I try, the write passes as if nothing is wrong. I can write multiple messages like this, and everything seems fine. It's only when I plug the cable back in that it sees that it's disconnected (all messages are buffered?).
The TcpClient
is set to NoDelay
, and there's a Flush()
called after every write anyway.
What I've tried:
- Writing a message to the
NetworkStream
- no joy CanWrite
,Connected
, etc all return trueTcpClient.Client.Poll( 1000, SelectMode.SelectWrite );
- returns trueTcpClient.Client.Poll( 1000, SelectMode.SelectRead ) && TcpClient.Client.Available == 0
- returns trueTcpClient.Client.Receive(buffer, SocketFlags.Peek) == 0
- when connected, blocks for about 10-20s, then returns true. When no server, blocks forever(?)NetworkStream.Write()
- doesn't throw an errorNetworkStream.BeginWrite()
- doesn't throw an error (not even when callingEndWrite()
)- Setting a
WriteTimeout
- had no effect - Having a specific time where we haven't received a message from the server (normally there's a keep-alive) - I had this, but removed it, as we were getting a lot of false-positives due to lag etc (some clients would see between 10-20s of lag)
So am I doing something wrong here? Is there any way to get the NetworkStream
to throw an error (like it should) when writing to a socket that should be disconnected?
I've no problem with a keep-alive (the default case is the server will notify the client that it hasn't received anything in a while, and the client will send a heartbeat), but at the minute, according to the NetworkStream
everything's hunky-dory.
It's for a game, so ideally the detection should be quick enough (as the user can still move through the game until they need to make a server call, some of which will block the UI, so the game seems broken).
I'm using Unity, so it's .Net 2.0
回答1:
is to pull out the network cable on the wifi box
That's a good test. If you do that the remote party is not notified. How could it possibly find out? It can't.
when I try, the write passes as if nothing is wrong
Writes can (and are) buffered. They eventually enter a block hole... No reply comes back. The only way to detect this is a timeout.
So am I doing something wrong here?
You have tried a lot of things but fundamentally you cannot find out about disconnects if no reply comes back telling you that. Use a timeout.
来源:https://stackoverflow.com/questions/31322716/tcpclient-networkstream-not-detecting-disconnection