如何判断基于套接字的客户端连接是否已经断开?

8

如果我的客户端在另一端断开连接(kill -9 server),需要几分钟才能确定出现了问题。即使连接实际上已经断开,Socket.Connected仍然返回true。

一旦另一端断开链接,最快的确定连接不存在的方法是什么?

客户端代码:

try{
      Socket socket= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     /*Assume there is a connection on the other end*/
      while (socket.Connected)
      {
    
          /*Do some processing*/
      }
 }catch (SocketException se){
       Console.WriteLine(ex.Message);
 } catch (Exception ex){
       Console.WriteLine(ex.Message);
 }
 finally
 {
   Console.WriteLine("something bad happen");
 }
6个回答

3

这对我来说似乎有效... 有人看到任何问题吗?

public bool IsConnected
{
         get {return !(Socket.Poll(1, SelectMode.SelectRead) 
                                  && m_socket.Available ==0)}
}

也可以放到扩展方法中。
public static class SocketExtensions
{
  public static bool IsConnected(this Socket @this)
  {
    return !(@this.Poll(1, SelectMode.SelectRead) && @this.Available == 0);
  }
}

现在,您可以轻松地将其用于处理套接字的代码中。
var mySocket = new Socket();
while(mySocket.IsConncted())
{
  // Do Stuff
}

没问题,但你的代码有点味道。你可以用 "return !(socket.Poll(1, SelectMode.SelectRead) && m_socket.Available == 0);" 替换你的方法体。 - Samuel
你甚至可以将它制作成一个扩展方法。public static class SocketExtensions { public static bool IsConnected(this Socket @this) { return !(@his.Poll(1, SelectMode.SelectRead) && @this.Available == 0); } } - Samuel
请更具体地描述问题,或将代码示例放入答案部分。谢谢。 - Sasha
该方法存在竞态条件,可能会导致错误的断开连接判断,详见此处 - Ian

1

尝试检查Available属性,当连接已关闭时,它应该抛出SocketException异常。

源代码

编辑,这是如何使用它的:

while(socket.Connected)
{
  try
  {
    while (socket.Available == 0)
      System.Threading.Thread.Sleep(100); // Zzzz
  }
  catch (SocketException)
  {
    // connection closed
    // do something
  }

  /* Do some processing */
}

您也可以尝试使用Poll方法。

来自:

或者,您还可以使用带有SelectRead SelectMode参数的Poll() Socket方法。如果数据可用或连接已被远程主机关闭,则此方法将返回true值。然后,您需要区分发生了哪种情况(通过读取套接字缓冲区,并查看它是否返回零值)。


无法正常工作,因为有时套接字已连接但没有可用数据,在我的情况下这是可以的...我想具体确定套接字已断开连接。 - Sasha
然后它的值为0。我看不出问题在哪里。阅读MSDN以获取Available属性的信息。"如果网络缓冲区中没有排队的数据,则Available返回0。""如果远程主机关闭或关闭连接,则Available可能会引发SocketException。" - Samuel
“can”并不意味着它会抛出异常...不可靠。 - Sasha

1

创建另一个线程,不断地向服务器发送请求 - 这是最好的方法,因为套接字并不是一种主动连接。


这有点复杂,你需要做一些研究,但据我所知,那应该是最可靠的方法。你的个人资料图片里是马特·塞拉吗? - George Mauer
我找到了一个解决方案。它是 GSP。 - Sasha

0
也许 SocketSendTimeout 和/或 ReadTimeout 属性可以帮助解决问题?

0

我参考我的答案 回答你关于此问题的 C++ 版本...


-1

你尝试过设置较短的连接超时时间吗?


虽然您可能认为设置较短的超时时间会有所帮助,但这并不能解决根本问题。Connected 属性的值来自于最后一次 IO 操作,即在最后一次读取/写入之后为 true。 - Samuel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接