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

发布于 2024-11-17 04:08:39 字数 340 浏览 2 评论 0原文

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

据我了解,这是因为“ICMP 目标无法访问”,它只是告诉服务器端口已关闭。没关系,但是两个 SocketException 都没有告诉我它来自哪个端点。

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

或者有没有办法让 Udpclient 停止抛出这些 SocketException,这样如果客户端在某几秒后没有响应,我可以使客户端超时。

I'm using a UdpClient at the server end and it is sending data to the client end (more than one client).
Suddenly the client stops listening on the udp port and the server gets hit with an SocketException, either when calling endRecieve or beginRecieve.

To my understanding this is because of an "ICMP Destination Unreachable" and it's just telling the server the port's closed. That's ok, but neither of the SocketExceptions tell me which endpoint it is from.

How can I know which endpoint is closed so the server stops sending to it and causing more SocketExceptions?

Or is there a way for Udpclient to stop throwing these SocketExceptions so I can make the clients timeout if they don't respond after so and so seconds.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你是我的挚爱i 2024-11-24 04:08:39

我自己正在处理同样的问题,所以我很想看看是否有人提出更好的解决方案,但现在我有几个想法:

我有一个通讯包装类(我们称之为 AsyncComm< /code>) 围绕我的套接字,在构造时从其所有者类传递异常处理程序委托。异常处理程序委托接受异常的参数和引发该异常的 AsyncComm 实例的引用。然后,我将

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

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

关于确定异常来自的终点,我现在唯一的想法是从 SocketException.Message 字符串的末尾解析终点,但这看起来相当混乱。

更新:这是一个拼凑,但它有效。解析下面的代码,其中一些代码取自此问题

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.");
    }
}

I'm dealing with the same issue myself so I'll be interested to see if anyone comes up with a better solution, but for now I have a couple ideas:

I have a comm wrapper class (let's call it AsyncComm) around my sockets that is passed an exception handler delegate from its owner class when it's constructed. The exception handler delegate takes arguments of an exception and a reference to the AsyncComm instance that threw it. I then put

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

in each of my async handler methods in AsyncComm so they can throw their exceptions up the chain. In my case, the exception handler uses the reference to the AsyncComm instance to call a method in the AsyncComm instance to tell it to reinitialize its socket. You can change that behavior to whatever you need to do to stop continuously getting SocketExceptions.

Regarding determining the end point the exception came from, the only idea I have right now is parsing the end point from the end of the SocketException.Message string, but that seems like quite a kludge.

Update: It is a kludge but it works. Parse code below, some of it taken from 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.");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文