我正在处理客户端/服务器关系,这种关系意味着在不确定的时间内来回推送数据。
我试图克服的问题是在客户端,因为我无法找到检测断开连接的方法。
我已经在其他人的解决方案中获得了几个通行证,从捕获IO异常到轮询所有三个SelectMode上的套接字。我也尝试过使用民意调查的组合,检查“可用”和“可用的”。插座的领域。
// Something like this
Boolean IsConnected()
{
try
{
bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead);
bool part2 = (this.Connection.Client.Available == 0);
if (part1 & part2)
{
// Never Occurs
//connection is closed
return false;
}
return true;
}
catch( IOException e )
{
// Never Occurs Either
}
}
在服务器端,尝试写一个空的'客户端的字符(\ 0)强制执行IO异常,服务器可以检测到客户端已断开连接(非常简单)。
在客户端,相同的操作不会产生异常。
// Something like this
Boolean IsConnected( )
{
try
{
this.WriteHandle.WriteLine("\0");
this.WriteHandle.Flush();
return true;
}
catch( IOException e )
{
// Never occurs
this.OnClosed("Yo socket sux");
return false;
}
}
我认为我在通过民意调查检测到断开连接时遇到的一个问题是,如果我的服务器自上次以来还没有将任何内容写回客户端,我很容易在SelectRead上遇到错误检查...不知道该怎么做,我已追查每个选项,以便我能找到这个检测,对我来说没有什么是100%,最终我的目标是检测服务器(或连接) )失败,通知客户,等待重新连接等等。所以我相信你可以想象这是一个不可或缺的部分。
感谢任何人的建议。 提前谢谢。
编辑:观看此问题的任何人都应该注意以下答案,以及我的最终评论。我已经详细说明了我是如何克服这个问题的,但还没有制作一个Q& A'风格的帖子。
答案 0 :(得分:12)
一种选择是使用TCP keep alive包。你打电话给Socket.IOControl()
打开它们。只有恼人的一点是它需要一个字节数组作为输入,所以你必须将你的数据转换成一个字节数组来传入。这里有一个例子,使用10000ms保持活着并重试1000ms:
Socket socket; //Make a good socket before calling the rest of the code.
int size = sizeof(UInt32);
UInt32 on = 1;
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds.
UInt32 retryInterval = 1000; //If no response, resend every second.
byte[] inArray = new byte[size * 3];
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null);
只有在您没有发送其他数据时才会发送保持活动数据包,因此每次发送数据时,10000ms计时器都会被重置。