如何找出导致SocketException的端点,UdpClient

时间:2011-06-23 06:31:35

标签: c# .net networking udp udpclient

我在服务器端使用UdpClient,它正在向客户端发送数据(多个客户端)。 突然,客户端停止侦听udp端口,并且在调用endRecieve或beginRecieve时服务器被SocketException命中。

据我所知,这是因为“ICMP Destination Unreachable”并且它只是告诉服务器端口已关闭。没关系,但SocketExceptions都没有告诉我它来自哪个端点。

我如何知道哪个端点已关闭,以便服务器停止向其发送并导致更多SocketExceptions?

或者是否有一种方法可以让Udpclient停止抛出这些SocketExceptions,这样我就可以让客户端超时,如果他们在几秒钟之后没有响应。

1 个答案:

答案 0 :(得分:0)

我自己也在处理同样的问题,所以我有兴趣看看是否有人想出更好的解决方案,但现在我有一些想法:

我有一个comm包装类(让我们称之为AsyncComm)围绕我的套接字,它在构造时从其所有者类传递异常处理程序委托。异常处理程序委托接受异常的参数以及对抛出异常的AsyncComm实例的引用。然后我把

try
{
   // Do stuff here
{
catch (Exception e)
{
   CallExceptionHandlerDelegate(e, this);
}

AsyncComm中的每个异步处理程序方法中,因此可以将它们的异常抛到链中。在我的例子中,异常处理程序使用对AsyncComm实例的引用来调用AsyncComm实例中的方法,以告诉它重新初始化其套接字。您可以将该行为更改为您需要做的任何事情,以便不断获取SocketExceptions

关于确定异常来自的终点,我现在唯一的想法就是从SocketException.Message字符串的末尾解析结束点,但这看起来像是一个很大的问题。

更新:这是一个kludge,但它的工作原理。解析下面的代码,其中一些来自this question

private IPEndPoint parseEndPointFromString(string input)
{
    // Matches 1-255.1-255.1-255.1-255:0-65535. I think.
    const string IPPortRegex = @"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):(6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)";

    Match match = Regex.Match(input, IPPortRegex);

    if (match.Success)
    {
        string IPPortString = match.Value;

        string[] ep = IPPortString.Split(':');
        if (ep.Length != 2) throw new FormatException("Invalid endpoint format");
        IPAddress ip;
        if (!IPAddress.TryParse(ep[0], out ip))
        {
            throw new FormatException("Invalid IP address");
        }
        int port;
        if (!int.TryParse(ep[1], out port))
        {
            throw new FormatException("Invalid port");
        }
        return new IPEndPoint(ip, port);
    }
    else
    {
        throw new FormatException("Invalid input string, regex could not find an IP:Port string.");
    }
}