TCP 客户端连接冻结程序
TCP client connection freezes program
我想在 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);
}
}
如果您希望您的应用程序保持响应而不是挂起,您不能构建自己的循环并保持线程被占用。相反,让 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);
}
}
}
如果您想对端口执行异步 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,并在服务器离线或出现问题时 returns -1。
我想在 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);
}
}
如果您希望您的应用程序保持响应而不是挂起,您不能构建自己的循环并保持线程被占用。相反,让 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);
}
}
}
如果您想对端口执行异步 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,并在服务器离线或出现问题时 returns -1。