【发布时间】:2019-06-23 14:19:19
【问题描述】:
我正在处理客户端/服务器关系,该关系旨在在不确定的时间内来回推送数据。
我试图克服的问题是在客户端,因为我无法找到检测断开连接的方法。
我对其他人的解决方案进行了几次尝试,从仅捕获 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% 的,最终我的目标是检测服务器(或连接)故障,通知客户端,等待重新连接等。所以我相信你可以想象这是一个不可或缺的部分。
感谢任何人的建议。 提前谢谢。
编辑:查看此问题的任何人都应注意下面的答案,以及我对它的最终评论。我已经详细说明了我是如何克服这个问题的,但还没有发布“问答”风格的帖子。
【问题讨论】:
-
只需捕获 IOExceptions,并使用读取超时。你不需要所有这些其他的恶意。
-
我已经试过了(以防你没有真正阅读我的帖子......),它的命中或错过。一秒后读取操作超时会导致 IO,这将强制断开连接...但是如果我只是没有收到数据怎么办...?
-
我读了你的帖子。它不是“命中注定”,它受到本地和远程异步数据缓冲的影响。在第一次写入失败的连接时不会出现异常,因为它尚未被检测到:在 TCP 已超时重试尝试之后,您将在后续写入时得到它。
-
很抱歉,我非常不同意。如果您愿意,我可以进行调试会话...
-
Socket.Receive 和 EndReceive() 当远程端关闭时返回零。这在 API 描述中有记录:如果您使用面向连接的 Socket,则 Receive 方法将读取尽可能多的数据,直到缓冲区的大小。如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且已经接收到所有可用数据,则 Receive 方法将立即完成并返回零字节。
标签: c# sockets tcpclient streamwriter