gpt4 book ai didi

c# - NetworkStream.ReadTimeout 在应用夏令时和时钟向后移动时无法阻止 NetworkStream.Read(...)

转载 作者:太空宇宙 更新时间:2023-11-03 17:06:38 27 4
gpt4 key购买 nike

我希望有人可以解释这种行为,或者它是否可能是 .NET 中的错误。

由于夏令时而及时向后移动意味着 NetworkStream 不注意其属性 ReadTimeout,并且在此代码的情况下会导致循环旋转。 (这只是一个证明它正在发生的例子)。

要重现我看到的问题,您需要设置一个使用夏令时的时区,例如英国。

  1. 将您的时区设置为 UTC London,并确保选中夏令时。
  2. 将日期改回 2017 年 10 月 29 日
  3. 将时间设置为凌晨 01:58:50
  4. 运行下面的代码,观察它在凌晨 2 点应用夏令时时旋转,如果应用正确,时间应该回到凌晨 1 点。
  5. 请务必等待,它最多可能需要 30 秒才能开始旋转。

编辑:经过深入调查,1 小时后,它停止旋转,行为恢复正常并遵守 ReadTimeout。

如有任何想法,我们将不胜感激!

客户端代码:

class Program
{
static bool running = false;

static void Main(string[] args)
{
running = true;
Task.Factory.StartNew(() => Run());

Console.ReadKey();

running = false;
}


static void Run()
{
TcpClient connection = new TcpClient("127.0.0.1", 1234);

while (running)
{
if (connection != null && connection.Connected)
{
try
{
NetworkStream stream = connection.GetStream();
stream.ReadTimeout = 1000;

byte[] buffer = new byte[1024];
int readCount = stream.Read(buffer, 0, 1024); // Should block here for the ReadTimeout duration if nothing received
// However when daylight savings is applied and time moves backwards an hour, the stream.ReadTimeout = 1000;
// is not honoured and it falls through and spins

if (readCount > 0)
{
Console.WriteLine("Received some data");
//process read here
}
else
{
Console.WriteLine("ReadTimeout was not honoured");
}
}
catch (IOException)
{
Console.WriteLine("Read timed out");
}
}
}
}
}

服务器代码:

class Program
{
static bool running = false;

public static void Main()
{
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 5000;
IPAddress localAddr = IPAddress.Parse("192.168.1.69");

// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);

// Start listening for client requests.
server.Start();

// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");

// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");


// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();

running = true;

Task.Factory.StartNew(() => Run(stream));


Console.ReadKey();

// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}


Console.WriteLine("\nHit enter to continue...");
Console.Read();
}

static async Task Run(NetworkStream stream)
{
byte[] stuffToSend = Encoding.ASCII.GetBytes("Stuff to send");
while (running)
{
stream.Write(stuffToSend, 0, stuffToSend.Length);
await Task.Delay(1000);
}
}
}

最佳答案

the OS documentation中有一些非常重要的注意事项.NET ReadTimeout 属性中未提及的内容:

SO_RCVTIMEO and SO_SNDTIMEO

When using the recv function, if no data arrives during the period specified in SO_RCVTIMEO, the recv function completes. In Windows versions prior to Windows 2000, any data received subsequently fails with WSAETIMEDOUT. In Windows 2000 and later, if no data arrives within the period specified in SO_RCVTIMEO, the recv function returns WSAETIMEDOUT, and if data is received, recv returns SUCCESS.

If a send or receive operation times out on a socket, the socket state is indeterminate, and should not be used; TCP sockets in this state have a potential for data loss, since the operation could be canceled at the same moment the operation was to be completed.

目前,在每次超时后,您都在循环并尝试在同一个套接字上进行另一个接收操作。但是这个注释非常清楚地表明您需要创建一个新连接。

关于c# - NetworkStream.ReadTimeout 在应用夏令时和时钟向后移动时无法阻止 NetworkStream.Read(...),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48710174/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com