C# 异步TCP客户端连接在Windows和Linux上部署时会有所不同
我正在编写一个客户端应用程序,它必须通过TCP套接字连接到服务器应用程序。选择的框架是.NET Core 2.0(它不是ASP.NET Core,只是一个控制台应用程序)。我正在使用C# 异步TCP客户端连接在Windows和Linux上部署时会有所不同,c#,linux,windows,asp.net-core,.net-core,C#,Linux,Windows,Asp.net Core,.net Core,我正在编写一个客户端应用程序,它必须通过TCP套接字连接到服务器应用程序。选择的框架是.NET Core 2.0(它不是ASP.NET Core,只是一个控制台应用程序)。我正在使用TcpClient类及其.BeginConnect()和.EndConnect()方法来设置连接超时。代码如下: public class Program { public static void Main(String[] args) { var c = new TcpClient(
TcpClient
类及其.BeginConnect()
和.EndConnect()
方法来设置连接超时。代码如下:
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();
}
当我编译、发布和运行这个控制台应用程序时,没有任何东西在侦听IP地址和端口,如果该应用程序在Windows或Linux上运行,结果会有所不同。
以下是Windows上的结果:
以下是它在Linux上的外观:
结果几乎相同,唯一的区别是在Windows上,它每两秒钟尝试连接一次,但在Linux上,它的行为就像这两秒钟被忽略一样,并进行我所称的“狂暴连接会话”。
我不确定这是否是一个.NET核心问题,或者是一些Linux调优,Windows已经预定义了。
任何人都可以提出可能存在的问题,并最终提出解决方案
提前感谢,
朱利安·迪米特罗夫(Julian Dimitrov)我想我理解你为什么会有问题,这似乎是基于对超时应该做什么的误解 为了测试,我将您的代码更改为:
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);
在Windows上,我可以看到连接在大约1秒后失败,而在Linux中运行相同的代码时,几乎会立即失败。Linux似乎能够计算出连接是否可能比Windows更快。我想你可能误解了Windows计算出它无法与你指定的超时连接所需的时间
下一步:什么是超时?超时是建立连接所需的最长时间。这是一个极限。这意味着操作必须在X秒内完成(如10秒),否则操作失败。如果一个操作在1秒内完成,那么它将立即返回。您是否进行了测试以检查您对WaitOne和TimeSpan的假设?将
TimeSpan
作为超时值,而不是等待时间。您正在等待异步任务(连接)完成。您的连接成功,因此一旦建立连接,它就会完成。在Win和Linux上的ManualResetEvent上调用的WaitOne()'的行为相同。在我使用
TimeSpan`之前,我刚刚输入了2000的毫秒数-两个操作系统的结果相同s@Julian返回一个。的文档表明这是一个延迟,而不是一个超时。应用程序结构的灵感来源于问题的答案。我找不到一种方法来测试IAsyncResult
上的WaitHandle.WaitOne
,该方法与.BeginConnect
方法分离。我仍然找不到一个合理的答案,为什么它可以在Windows上工作而不能在Linux上工作……我发现了另一件有趣的事情,当您删除success=res.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10))代码>示例中的行。。。。它在Windows ans Linux上的作用是相同的:)这是因为,通过删除等待,您正在异步尝试连接,而不是等待结果。因此,无论您在.AsyncWaitHandle.WaitOne()
中添加了什么内容,always-on Windows都将在大约1秒内尝试重新连接,但在Linux上几乎是立即的Julian,这是因为你只定义了它所能花费的最长时间,而不是延迟。如果要插入延迟,则需要在失败时使用类似于Thread.Sleep的方法。是的,由于您的解释,我理解了这个问题,操作将是放置Thread.Sleep()
以插入延迟。谢谢你的回答!