问题
I have a few questions about finishing a tcp connection.
A client connects to my server using Tcp, after accepting the client with
listener.BeginAcceptTcpClient(ConnectionEstabilishedCallback, null);
, I start to read withnetworkStream.BeginRead(....)
.
What happens when the client disconnects while I wait for a message? (e.g. it loses power, internet, etc)
How do I know when it happens?If after a successful read, I do some stuff, and then call
networkStream.Close(); client.Close();
What will the client see? How do I terminate the connection "gracefully"?What happens if I'm waiting for a read (with BeginRead), and then (on a different thread) close the same stream?
EDIT TO ADD: I do have a ping-pong message going on between the client and server. Is that enough? If I don't receive ping, terminate my NetworkStream? surely there must be something better.
回答1:
1- If the client disconnected due to cable unplugged you will not know till the next read or write to the socket. also note that the tcpClient.Connected property value is not reliable, it's value depending on the last communication; so if the last communication were succeed then it's value is true otherwise it is false. for more information on that check this.
2- If you close the network stream and the client this is the gracefully termination of the client.
3- I don't know, give it a test.
If you aware from connection lost because of a cable unplugged or so, then to get appropriate IsConnected value you have to be aware from the connection lost during the read or write to the tcp, so you need to access the tcpclient members by potting a try-catch around its operation....
Use this IsConnected property to check if the tcpClient is connected:
public static bool IsConnected
{
get
{
try
{
//return _tcpClient != null && _tcpClient.Client != null && _tcpClient.Client.Connected;
if (_tcpClient != null && _tcpClient.Client != null && _tcpClient.Client.Connected)
{
/* As the documentation:
* When passing SelectMode.SelectRead as a parameter to the Poll method it will return
* -either- true if Socket.Listen(Int32) has been called and a connection is pending;
* -or- true if data is available for reading;
* -or- true if the connection has been closed, reset, or terminated;
* otherwise, returns false
*/
// Detect if client disconnected
if (_tcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (_tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
// Client disconnected
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
}
回答2:
What happens when the client disconnects while I wait for a message? (e.g. it loses power, internet, etc) How do I know when it happens?
Different things happens for different disconnect reasons.
A graceful disconnection is detected when you receive 0 bytes from socket.EndRead
. Other shutdowns will lead to SocketException
for either EndRead
or Send
If after a successful read, I do some stuff, and then call networkStream.Close(); client.Close(); What will the client see? How do I terminate the connection "gracefully"?
Close will do it gracefully.
What happens if I'm waiting for a read (with BeginRead), and then (on a different thread) close the same stream?
You'll get an exception. Either ObjectDisposedException
(if you dispose the client) or IOException
回答3:
public class Example
{
static NetworkStream stream;
static TcpClient client;
public static void Main(String[] args)
String message = String.Empty;
//TCP connection
Recon: Console.WriteLine("Connecting...");
Int32 port = 3333;
try
{
client = new TcpClient("ip.ip.ip.ip", port); //Try to connect
}
catch
{
Console.WriteLine("Problem while connecting!");
Thread.Sleep(10000); //Waiting 10s before reconnect
goto Recon;
}
Console.WriteLine("Connection established!\n");
stream = client.GetStream();
while (true)
{
//Buffer
byte[] received_bytes = new Byte[1024];
message = "";
Console.WriteLine("Waiting to receive message...\n");
Int32 bytes = stream.Read(received_bytes, 0, received_bytes.Length);
message = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(received_bytes, 0, bytes);
if (bytes == 0) //If connection abort while reading
{
Console.WriteLine("Connection failed!");
//Recconecting
goto Recon;
}
Console.WriteLine("Received message: " + message);
}
}
}
来源:https://stackoverflow.com/questions/6452992/tcpclient-disconnect-during-async-read