Windows 操作系统中无法访问的 IP 套接字关闭时间

Posted

技术标签:

【中文标题】Windows 操作系统中无法访问的 IP 套接字关闭时间【英文标题】:Unreachable IP Socket Close Time in Windows OS 【发布时间】:2017-06-22 08:25:37 【问题描述】:

这些代码通过用户数据报协议提供发送数据。下面有两个代码。当我将第一个代码用于无法访问的 IP 地址时,我得到了三秒的延迟。


请查看新结果标题


只需打开新的 C# 控制台应用程序并将这些代码粘贴到其中即可。 (第一个代码)

using System;
using System.Net;
using System.Net.Sockets;

namespace Test

    class Program
    
        static void Main(string[] args)
        
            byte[] data =  1, 20, 60, 44, 244 ;
            while (true)
            
                Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
                try
                
                    using (var client = new UdpClient())
                    
                        // Please check IP Address, It must be unreachable...
                       // IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.1.141"), 55600);
                      //  client.Connect(ep);
                        client.Send(data, data.Length, "192.168.1.141" , 55600);
                    
                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
                    Console.WriteLine("    ");
                
                catch (Exception ex)
                
                    Console.WriteLine(ex.ToString());
                
            
        
    

测试 1(使用):可访问 IP测试 2(使用):无法访问 IP输出: Test1 label1 ---> h:mm:ss label2 ---> h:mm:ss(同一时间)Test2 label1 ---> h:mm:ss label2 ---> h:mm:ss +3 秒(无异常)

WireShark 结果:测试 1(使用):可访问的 Ip --> 数据被捕获,可见。测试 2( with using) : 无法访问 IP-> 无数据。

当我在没有“使用”块的情况下使用时,我没有得到三秒 延迟。

只需打开新的 C# 控制台应用程序并将这些代码粘贴到其中即可。 (第二个代码)

using System;
using System.Net;
using System.Net.Sockets;

namespace Test

    class Program
    
        static void Main(string[] args)
        
            byte[] data =  1, 20, 60, 44, 244 ;
            while (true)
            
                Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
                try
                
                    var client = new UdpClient();
                    //Please check IP address, It must be unreachable...
                   // IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.1.41"), 5600);
                   // client.Connect(ep);
                    client.Send(data, data.Length, "192.168.1.141", 55600);

                    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
                
                catch (Exception xe)
                
                    Console.WriteLine(xe.ToString());
                
                Console.WriteLine("   ");
                System.Threading.Thread.Sleep(1000);
            
        
    

测试 1(未使用):可访问的 Ip测试 2(未使用):无法访问的 Ip

输出:Test1 label1 ---> h:mm:ss (Same Time) label2 ---> h :mm:ss(同一时间)Test2 label1 ---> h:mm:ss(同一时间) label2 ---> h:mm:ss (同一时间)(无一例外)

WireShark 结果:测试 1(不使用):可达 IP --> 数据被捕获,可见。测试 2(不使用):无法访问IP->没有数据。

三秒延迟是什么意思? 我不确定,但我认为我必须使用“使用”块,因为如果我不使用块,内存使用量会增加非常高的阶段。 两种代码有什么区别?哪个更可靠?有没有更好的办法?我不想要三秒的延迟。

如何将三秒延迟降至零?

提前谢谢...


新结果

我已经尝试使用 Python 编程关闭/处理无法访问的 IP 的套接字 Windows 操作系统中的语言。我得到了相同的结果,即无法到达的三秒延迟 知识产权。但是当我在 Ubuntu 15.10 中尝试相同的 Python 代码时,我没有得到 三秒延迟。

import socket
import datetime

IPADDR = '192.168.1.141'
PORTNUM = 5600
PACKETDATA = "f1a525da11f6".encode()

while(True):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
    s.connect((IPADDR, PORTNUM))
    s.send(PACKETDATA)
    print(datetime.datetime.now())
    s.close()

【问题讨论】:

请格式化您的代码,适当缩进。不透露其结构的代码真的很难阅读。 请提供可重现的示例。以您提供的示例为例,我无法在 dispose\close 上重现该延迟。 非常感谢。我已经更新了代码。请,再次审查。只需在新的控制台应用程序中复制代码即可。提前谢谢。 @Evk 有时间我会去看看,但仅仅因为我建议你如何改进问题并不一定意味着我能够解决它。 (与其说“将代码粘贴到新的控制台应用程序中”,不如包含所有代码更有帮助,这样我们就可以复制/粘贴到一个全新的文件中,编译并运行.. .) 关闭需要一些时间,因为发送缓冲区中有待处理的数据(我认为),但我不知道如何防止这种情况。对于 TCP 套接字,您可以使用 Linger 套接字选项立即关闭套接字而无需等待,但对于似乎不适用的 UDP 套接字。 【参考方案1】:

您的 UdpClient 是一次性对象。您应该在重新连接之前将其丢弃。

            using (var client = new UdpClient())
                //Please check IP address, It must be unreachable...
                IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.1.41"), 5600);
                client.Connect(ep);
                client.Send(data, data.Length);
            

或将连接移出循环以重复使用相同的连接。

【讨论】:

感谢您的回答。如果你看上面的“新结果”标题。您可以在 Windows 中使用 Python 代码看到相同的三秒延迟。问题与 Windows 操作系统有关。 @彼得【参考方案2】:

实际的区别是在 SECOND CODE 中 client 上没有调用 Dispose() 方法。但是 Dispose() 在 FIRST CODE 中以 using (var client = new UdpClient()) 调用。在尝试连接无法访问的 IP 地址后调用 Dispose() 方法需要 3 秒的额外时间。

您可以如下所示的第二个代码来注意打印最后一个标签的延迟。延迟是由Dispose 引起的。 client 必须在 try 块上方声明才能在 finally 块中使用。

finally

    if (client != null)
        ((IDisposable)client).Dispose();

Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));

我还注意到,如果无法访问的 IP 地址在域外,也不会导致延迟。例如,如果我的 PC 的 IP 是 192.168.1.20 并且我尝试访问 202.22.1.88 则看不到延迟。

结论是:延迟是由Dispose()引起的。但应进一步调查Dispose() 的行为。

【讨论】:

感谢您的回答。而且我知道延迟三秒的原因。但我不知道如何取消三秒延迟。问题与 Windows 操作系统有关。 Bcz 我在 Python 代码中遇到了同样的三秒延迟。但我没有使用 Ubuntu.... UdpClient.Dispose() 方法调用InternalShutDown()Close() 的internal socket object。有关更多详细信息,请参阅调用非托管函数的 Socket.Dispose() method。【参考方案3】:

将三秒延迟降低到零解决方案一(配合线程池使用):


while (true)

    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
    try
    
        ThreadPool.QueueUserWorkItem(state =>
        
            using (var client = new UdpClient())
                                       
                client.Send(data, data.Length, "192.168.1.145", 55600);   
                                   
        );
        Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
        Console.WriteLine("    ");
    
    catch (Exception ex)
    
        Console.WriteLine(ex.ToString());
    
    System.Threading.Thread.Sleep(1000);   // to see easily
 

将三秒延迟减少到零解决方案 1(client=null):


while (true)

    Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
    try
                     
        var client = new UdpClient();                                                
        client.Send(data, data.Length, "192.168.1.145", 55600);
        client = null;                                            

        Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt"));
        Console.WriteLine("    ");
    
    catch (Exception ex)
    
        Console.WriteLine(ex.ToString());
    
    System.Threading.Thread.Sleep(1000); // to see easily

【讨论】:

以上是关于Windows 操作系统中无法访问的 IP 套接字关闭时间的主要内容,如果未能解决你的问题,请参考以下文章