【问题标题】:c# socket check connectionc# socket检查连接
【发布时间】:2023-06-04 15:20:02
【问题描述】:

我正在尝试为特定端口建立与主机/IP 地址的套接字连接。我尝试实现的主要目标是:

  • 获取展位成功/失败连接的响应时间(以毫秒为单位)
  • 使用自定义超时,例如 5 秒 (5000)

所以基本上如果我指定一个主机名,如google.com 和端口80 这应该检查连接是否有效,如果我指定173.194.70.101 和端口80 它应该工作。

如果我指定例如主机名 google.com 和端口 7788 这应该不起作用,因为该端口未打开。如果我指定 IP:173.194.70.101 和端口“7788”,这应该不起作用。

如果我指定一些随机主机,例如 sdfzsdfaklsf.com 和端口 7788,这应该不起作用,因为主机不存在。

对于上述所有情况,我需要所有成功/失败的响应时间...

我最终得到了这段代码,并且接缝可以正常工作,但是我想问一下这是否是正确的做法?

     public string CheckConnection(string ipAddressOrHostName, string portName)
    {
        Stopwatch timer = new Stopwatch();
        timer.Start();
        Socket server = null;
        string elapsed = string.Empty;

        try
        {

            IPHostEntry hostEntry = Dns.GetHostEntry(ipAddressOrHostName);

            IPAddress ipAddress = hostEntry.AddressList[0];

            IPEndPoint ip = new IPEndPoint(ipAddress, Convert.ToInt32(portName));

            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IAsyncResult result = server.BeginConnect(ip, null, null);

            result.AsyncWaitHandle.WaitOne(5000, true);

            timer.Stop();

            elapsed = timer.ElapsedMilliseconds.ToString();


            if (!server.Connected)
            {                    
                server.Close();
                throw new Exception();
            }
            else
            {   
                string status = string.Format("Connected succesfully to: {0} in: {1} milliseconds", server.RemoteEndPoint.ToString(), elapsed);                   
                server.Shutdown(SocketShutdown.Both);
                server.Close();

                return status;
            }
        }
        catch (Exception)
        {
            timer.Stop();

            elapsed = timer.ElapsedMilliseconds.ToString();

            return string.Format("Connection failed to: {0}:{1} in: {2} milliseconds", ipAddressOrHostName, portName, elapsed);                     
        }

    }

【问题讨论】:

  • 我会改进您的异常处理。不建议捕获一般异常并将其视为特定的网络/连接故障。还可以尝试将您的关闭/关闭/停止调用放入“最终”块中......除此之外,我认为这看起来不错......

标签: c# sockets asyncsocket


【解决方案1】:

还不错。几点:

  1. 捕获更特定类型的异常并对其进行测试。您不想捕获不相关的东西或隐藏错误。
  2. 启动计时器 您完成 DNS 解析之后。
  3. throw new Exception 不太好,因为异常并不意味着控制流。重新构建方法,使其不再需要这种 hack。
  4. 您可能希望使用 tasks 而不是 IAsyncResult。没有功能变化,只是更现代的风格。
  5. 您在一些地方有冗余(例如重复关闭、重复 ToString)。
  6. 在方法之外解析端口。它不属于那里。事实上,如果端口是不可解析的,你会在此刻触发感知超时,因为会抛出异常。这就是我用第 (1) 点警告你的地方。过多使用异常会导致一个您可能永远不会知道的错误,因为它被隐藏了。

【讨论】:

  • 你能告诉我如何实现异步等待而不是 IAsyncResult 吗?
  • 我认为这超出了这个问题的范围。搜索“等待套接字”以找到答案。如果您还有其他问题,请告诉我。
  • 我确实实现了 async-await 而不是 IAsyncResult,但我失去了对自定义超时的控制,我认为默认为 20 秒……但无论如何感谢您的 cmets!
  • 明确我不建议在这里等待。我只是推荐了没有等待的任务(例如 Task.Wait(5000))。但这只是一个微弱的偏好。