我有一个使用TcpClient和TcpListener通过网络进行通信的应用程序。但是,当我在客户端上调用TcpClient.Close以断开它与服务器的连接时,服务器根本不会做出反应。
现在,在您发布关于此问题的评论与this的问题重复之前,以及如何找到解决方案here之前,相信我,当我说我已经找到这些和尝试过他们。它没有帮助。我还尝试了TcpClient.Close
,TcpClient.GetStream().Close()
和TcpClient.Dispose
的不同组合。什么都行不通。
代码没有什么值得注意的,只是客户端中的Disconnect方法重置所有变量以便重用,并关闭所有网络资源。服务器有一个循环来检查TcpClient.Connected
是否为真,如果它是假的,它应该跳出循环并终止该线程。
有什么想法吗?
答案 0 :(得分:8)
TcpClient.Connected
几乎应该被忽略。它基本上代表了最后一次沟通是否成功。来自MSDN(强调我的):
由于Connected属性仅反映最近操作时的连接状态,因此您应尝试发送或接收消息以确定当前状态。消息发送失败后,此属性不再返回true。请注意,此行为是设计使然。您无法可靠地测试连接状态,因为在测试和发送/接收之间的时间内,连接可能已丢失。 您的代码应该假设套接字已连接,并正常处理失败的传输。
如果你在客户端调用Close()
,没有任何内容发送到服务器告诉它关闭它,它实际上只是自己关闭它,以便客户端不能再使用它。确定您是否仍然连接的唯一可靠方法是尝试发送数据并处理故障。如果你想要,你可以实现自己的握手协议,当你打电话给Close()
时,你会向服务器发送一个特殊通知,提醒它事实,但仍然有时候该数据包永远不会到达服务器。
答案 1 :(得分:0)
听一个字节,如果已收到,请完成剩下的工作。 如果接收一个字节返回0,则客户端断开连接。
IPAddress nReceiveAddress = IPAddress.Parse(GetIp(sSource));
IPEndPoint localEndPoint = new IPEndPoint(nReceiveAddress, GetPort(sSource));
Socket nSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
nSocket.Bind(localEndPoint);
nSocket.Listen(10);
Socket nSocketClient = nSocket.Accept();
byte[] bufferOne = new byte[1];
int nBytes = nClient.Receive(bufferOne);
if (nBytes == 0)
{
AppendToLog(String.Format("{0}: Closing.", sName));
nClient.Close();
}
else
{
byte[] buffer = null;
buffer = new byte[nClient.Available + 1];
if (nClient.Available > 0)
nBytes = nClient.Receive(buffer);
if(nBytes>0)
{
//KS effectively insert the first received byte at start.
Array.Copy(buffer, 0, buffer, 1, buffer.Length - 1);
buffer[0] = bufferOne[0];
}
}