【问题标题】:TCP client connection freezes programTCP客户端连接冻结程序
【发布时间】:2015-02-25 21:10:44
【问题描述】:

我想在 ip + 端口上进行异步连续 ping 请求。 问题是,当目标服务器离线时,整个程序在请求期间冻结。但这不应该发生。

这是我的 ping 函数,在启动程序时会调用一次。 它应该每 3 秒执行一次 ping 请求。

    public async void Start(string ip)
    {
        Stopwatch watch = new Stopwatch();

        while (true)
        {
            watch.Restart();
            using (TcpClient tcp = new TcpClient())
            {
                //try to connect to a closed port
                IAsyncResult res = tcp.ConnectAsync("127.0.0.1", 1234);

                //during the following while-loop the whole program freezes
                //although this is an asynchronous function
                while (watch.ElapsedMilliseconds < 1000) 
                {
                    if (tcp.Connected)
                    {
                        break;
                    }
                }
                watch.Stop();
                if (tcp.Connected)
                {
                    StatusControl.Text = watch.ElapsedMilliseconds.ToString() + " ms";
                }
                else
                {
                    StatusControl.Text = "Offline";
                }
            }
            //wait 3secs for the next request
            await Task.Delay(3000);
        }
    }

【问题讨论】:

  • 如果你想ping一台机器,使用ping,而不是tcpClient.Connect
  • 遗憾的是,Ping 不支持端口,不是吗?
  • perlmonks.org/?node=xy+problem 解释一下你真正的问题怎么样。

标签: c# .net asynchronous tcpclient freeze


【解决方案1】:

如果您希望您的应用程序保持响应并且不挂起,您不能构建自己的循环并保持线程被占用。相反,让 C# 使用 await 关键字为您管理任务。无需循环和检查超时,只需使用SendTimeout 为请求设置超时。这是一个例子:

    public async void Start(string ip)
    {
        label1.Text = "Begin";
        Stopwatch watch = new Stopwatch();

        while (true)
        {
            watch.Restart();
            using (TcpClient tcp = new TcpClient())
            {
                //try to connect to a closed port
                // First set a timeout value
                tcp.SendTimeout = 1000;
                try
                {
                    await tcp.ConnectAsync("127.0.0.1", 1234);
                }
                catch (SocketException)
                {
                    Debug.Assert(!tcp.Connected);
                }

                watch.Stop();
                if (tcp.Connected)
                {
                    label1.Text = watch.ElapsedMilliseconds.ToString() + " ms";
                }
                else
                {
                    label1.Text = "Offline";
                }
            }
            //wait 3secs for the next request
            await Task.Delay(3000);
        }
    }
}

【讨论】:

  • 我应该花更多时间研究 tcpclient 类,也许那时我会看到它有自己的超时属性。 >.> 非常感谢:)
  • 我注意到 timeout 属性不适用于连接建立。无论如何,我找到了一个异步 TCPclient ping 请求超时的解决方案。只要花费的时间超过给定的超时值,我就简单地处理我的 tcpclient。
  • @Showdown 您能否分享有关您的评论“超时属性不适用于连接建立”的任何链接或信息。
【解决方案2】:

如果您想对端口执行异步 ping 请求以及超时,此代码为我完成了:

    private async Task<long> Ping(string host, int port, int timeOut)
    {
        long elapsed = -1;
        Stopwatch watch = new Stopwatch();

        using (TcpClient tcp = new TcpClient())
        {
            try
            {
                using (CancellationTokenSource cts = new CancellationTokenSource())
                {
                    StartConnection(host, port, tcp, watch, cts);
                    await Task.Delay(timeOut, cts.Token);
                }
            }
            catch {}
            finally
            {
                if (tcp.Connected)
                {
                    tcp.GetStream().Close();
                    elapsed = watch.ElapsedMilliseconds;
                }
                tcp.Close();
            }
        }

        return elapsed;
    }

    private async void StartConnection(string host, int port, TcpClient tcp, Stopwatch watch, CancellationTokenSource cts)
    {
        try
        {
            watch.Start();
            await tcp.ConnectAsync(host,port);
            watch.Stop();
            cts.Cancel();
        }
        catch {}
    }

它只是在时间结束后立即处理 tcpClient,并在服务器离线或出现问题时返回 -1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-18
    • 2011-07-25
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多