【问题标题】:C# - Avoid getting a SocketExceptionC# - 避免获得 SocketException
【发布时间】:2013-05-02 09:26:08
【问题描述】:

我想知道是否有办法避免在我无法连接时获得 SocketException,而不是使用 try/catch 捕获 SocketException。

我有这段代码可以检查服务器是否可用:

public bool CheckServerStatus(string IP, int Port)
    {
        try
        {
            IPAddress[] IPs = Dns.GetHostAddresses(IP);

            using (Socket s = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp))
            s.Connect(IPs[0], Port);

            return true;
        }
        catch (SocketException)
        {
            return false;
        }
    }

提前致谢。

【问题讨论】:

  • 您为什么要这样做?你不能在 catch 语句中什么都不做吗?
  • 根据 msdn:当网络发生错误时,Socket 和 Dns 类会抛出 SocketException。所以这意味着你不能完全避免它

标签: c# sockets exception disconnect


【解决方案1】:

您可以继承 Socket 并提供您的具体实现:

public class MySocket : Socket{
    //...
    public boolean TryConnect(...){
    }
}

您也可以代替布尔值,返回一个 Result 对象来保存异常以进行错误处理:

public class Result {
    public Exception Error { get; set; }
    public boolean Success { get{ return Error != null; } }
}

【讨论】:

  • 您可以这样做,但这只会将“问题”转移到另一个地方。在那个TryConnect 方法中,你仍然会在同样的情况下得到一个SocketException。你只是在不同的地方处理它。
  • 是的,但是如果打算重用这个类,您将在 only one 点处理它。
  • 这是一个优势,是的,尽管这不是他所要求的,因为他特别要求避免异常本身。但是,根据他创建套接字的次数,这确实可能是一种更清洁的方法:)
【解决方案2】:

获得SocketException 不是问题;这就是应该使用异常的目的。根据您获得的异常类型,您可以采用不同的方式处理它们。如果你只是抓到Exception 而不是更具体的SocketException,那就太糟糕了。

你为什么这么想避免它?正如 cmets 所说,如果连接的另一端不可用,代码将在某个时间点、某处失败。只要确保你在适当的地方发现失败,就像你现在正在做的那样。

【讨论】:

  • 不一定。失败可能是有效的结果,而不是“异常”。故障可以在 UI 中显示或存储。对流控制使用异常是一个坏主意,我讨厌 BCL 在许多 API 中似乎都有这样做的功能。最好返回一个结果并让用户决定如何处理它。
  • 顺便说一句,刚刚测试了异常与否,25x perf hit。在某些情况下可能很好,在其他情况下可能不太好。
【解决方案3】:

我设法使用BeginConnect 完成此操作,如下所示

int connectTimeoutMS = 1000;
IPEndPoint endPoint = GetEndPoint();
var evt = new AutoResetEvent(false);
_socket.BeginConnect(endPoint, (AsyncCallback)delegate { evt.Set(); }, null);
evt.WaitOne(connectTimeoutMS);

【讨论】:

    【解决方案4】:

    也许您可以通过使用Ahmed approach 来解决问题,但这只是将问题推得更深。

    不存在这种测试方法的主要原因是可能存在竞争条件。想象一下,您会检查这样的套接字是否可能,并且在您尝试在下一行中建立此套接字之前,会发生上下文切换(到另一个线程或应用程序),它只是为自己分配此套接字。现在你仍然得到异常,你必须检查它(通过使用 try-catch 方法)。

    所以这个测试对你的代码没有任何好处,因为你仍然需要为这个方法的失败做好准备。这就是这个测试不存在的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 2016-07-08
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多