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 套接字关闭时间的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Windows 2012 MSMQ 中连接 Winsoc 套接字

Windows套接字编程中主机名的IP地址

git ssh 无法访问主机但使用直接 IP 时成功(Windows 10)

windows 2012 server r2无法访问互联网

无法在 Windows Server 2008 R2 上启动 Apache

AWS EC2 Windows实例无法通过公共IP访问