Windows和Linux兼容的tcp,异步TcpClient Connect在Windows和Linux上部署时有所不同

I'm writing a client application, that has to connect to a server application via TCP socket. The framework of choice is .NET Core 2.0 (it is not ASP.NET Core it is just a console app). I'm using a TcpClient class, and its .BeginConnect() and .EndConnect() methods, to be able to set a connection timeout. Here is the code:

public class Program

{

public static void Main(String[] args)

{

var c = new TcpClient();

int retryCount = 0;

var success = false;

IAsyncResult res;

do

{

if (retryCount > 0) Console.WriteLine("Retry: {0}", retryCount);

retryCount++;

c.Close();

c = new TcpClient();

res = c.BeginConnect("10.64.4.49", 13000, null, null);

success = res.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2));

Console.WriteLine(success.ToString());

}

while (!c.Connected);

c.EndConnect(res);

Console.WriteLine("Connected");

Console.ReadLine();

}

When I compile, publish and run this Console App, and nothing is listening on the IP address and port, the results if the app is running on Windows or Linux are different.

Here are the results on Windows:

f968520dd045cf90a3959acb06de916b.png

Here is what it looks like on Linux:

a4fb6682974023c8bce85edae7bdd698.png

The results are pretty the same, the only difference is on Windows it tries to connect every two seconds, but on Linux, it acts like this two seconds are ignored and goes on a "rampage connection session" as I call it.

I'm not sure if this is a .NET Core issue or some Linux tune-up, that Windows already have predefined.

Can anyone advice what might be the problem, and eventually propose a solution.

Thanks in advance,

Julian Dimitrov

Talk1:

Did you make a test to check your assumption about WaitOne and TimeSpan?

Talk2:

WaitOne takes a TimeSpan as a timeout value, not as a wait time. You're waiting for the async task (connecting) to complete. Your connection is successful, so it completes as soon as the connection is established.

Talk3:

The WaitOne()' called on a ManualResetEvent on both Win and Linux act the same. Before I useTimeSpan` I just entered 2000 for the amount of miliseconds - result the same on both OS's

Talk4:

BeginConnect returns an IAsyncResult. The documentation for ManualResetEvent.WaitOne suggests it is a delay, vs WaitHandle.WaitOne which suggest it is a timeout.

Talk5:

The app structure is inspired from the answer of this question. I can't find a way to test WaitHandle.WaitOne on the IAsyncResult separate from the .BeginConnect method. Still I can't find a reasonable answer, why it works on Windows and not on Linux...

Solutions1

I think I understand why you're having an issue, and it seems to be based upon a misunderstanding of what a timeout should do.

For the sake of testing, I changed your code to this:

var sw = Stopwatch.StartNew();

res = c.BeginConnect("127.0.0.1", 12, null, null);

success = res.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10));

sw.Stop();

Console.WriteLine(sw.ElapsedMilliseconds);

On Windows, I can see that the connection fails after ~1 second, whereas running the same code within Linux, it fails almost instantly. It seems that Linux is capable of working out if a connection is possible faster than Windows is. I think perhaps you're mistaking the time Windows takes to work out it can't connect with the timeout you've specified.

Next: What is a timeout? A timeout is the maximum time a connection can take to be established. It's a limit. It means that the operation has to complete in less than X seconds (e.g. 10 seconds) or it fails. If an operation completes in 1 second, then it will be immediately returned.

Talk1:

Another interesting thing I found, when you remove the success = res.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10)); line from the example.... it acts the same on Windows ans Linux :)

Talk2:

That's because, by removing the wait, you're asynchronously trying to connect, and then not waiting to find out the result.

Talk3:

So, no matter what you put in the .AsyncWaitHandle.WaitOne(), always on Windows will try to reconnect in about 1 sec, but on Linux almost immediately

Talk4:

Julian, It's because you're only defining the maximum time it can take - it's not a delay. You need to use something like Thread.Sleep when it fails if you want to insert a delay.

Talk5:

yes, I understood the problem, thanks to your explanation, and the action will be to put Thread.Sleep() to insert a delay. Thanks for your answers!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值