【问题标题】:How can I tell if the connection has been broken in my sockets based client?如何判断基于套接字的客户端中的连接是否已断开?
【发布时间】:2010-10-15 11:25:24
【问题描述】:

如果我的客户端在另一个end( 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");
 }

【问题讨论】:

    标签: c# .net networking sockets


    【解决方案1】:

    您是否尝试过设置更短的连接超时?

    【讨论】:

    • 虽然您可能认为设置更短的超时时间会有所帮助,但这并不能解决根本问题。 Connected 从最后一次 IO 操作中获取其值,在最后一次读/写后为真。
    【解决方案2】:

    生成另一个不断 ping 服务器的线程——这确实是你能做的最好的事情,因为套接字不是活动连接。

    【讨论】:

    • 它比较复杂,你必须做一些研究,但据我所知,这将是最可靠的方法。你头像中的那个是马特·塞拉吗?
    • 我找到了解决方案。普惠制
    【解决方案3】:

    尝试检查Available 属性,它应该在连接关闭时抛出SocketException

    Source

    编辑,以下是您的使用方法:

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

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

    来自Source

    或者,您也可以使用 Poll() Socket 方法与 SelectRead SelectMode 参数。这 方法将返回一个真值,如果 数据可用或如果连接 已被远程主机关闭。 然后你需要区分 这些情况之间有 发生(通过读取套接字 缓冲区,并查看它是否返回一个 零值)。

    【讨论】:

    • 不工作 b/c 有时套接字已连接并且没有可用的数据,在我的情况下这很好......我想具体确定套接字已断开连接
    • 那么它的值为0。我看不出问题。阅读可用属性的 MSDN。 “如果网络缓冲区中没有数据排队,可用返回 0。” “如果远程主机关闭或关闭连接,Available 会抛出 SocketException。”
    • "can" 不代表会抛出异常……不靠谱。
    【解决方案4】:

    也许SocketSendTimeout 和/或ReadTimeout 属性会有所帮助?

    【讨论】:

      【解决方案5】:

      这似乎对我有用...有人发现任何问题吗?

      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);”。
      • 你甚至把它变成了一个扩展方法。公共静态类 SocketExtensions { public static bool IsConnected(this Socket @this) { return !(@his.Poll(1, SelectMode.SelectRead) && @this.Available == 0); } }
      • 更具体或将代码示例放入答案部分。谢谢
      • 此方法存在竞争条件,如here 所述,可能会错误地判断断开连接。
      【解决方案6】:

      我将您推荐给 my answer 来回答您的 C++ 版本的这个问题...

      【讨论】:

        猜你喜欢
        • 2010-12-20
        • 2013-12-31
        • 1970-01-01
        • 2014-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-10
        相关资源
        最近更新 更多