避免得到SocketException

本文关键字:SocketException | 更新日期: 2023-09-27 18:11:52

我想知道是否有一种方法可以避免在我无法连接时获得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;
        }
    }

避免得到SocketException

您可以子类化Socket并提供您的具体实现:

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

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

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

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

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

我使用BeginConnect实现了这一点,如下所示

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

也许您可以使用Ahmed方法首先解决问题,但这只是将问题推向更深层次。

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

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