I'm hoping someone can explain this behaviour, or if it's maybe a bug in .NET.
Moving backwards in time due to daylight savings means that NetworkStream pays no attention to its property ReadTimeout, and in the case of this code causes the loops to spin. (This is just an example to prove it's happening).
To reproduce the problem I am seeing, you will need to be set to a timezone that uses daylight savings, e.g. The United Kingdom.
- Set your TimeZone to UTC London and make sure the daylight savings time is ticked.
- Change your date back to 29th October 2017
- Set your time to 01:58:50 am
- Run code below and watch it spin when it applies the daylight saving time at what would be 2am, if it applies it correctly time should move back to 1am.
- Make sure you wait, it can take up to 30 seconds for it to start spinning.
Edit: After deeping investigation, after 1 hour, it stops spinning and the behaviour returns to normal and honours the ReadTimeout.
Any thoughts would be appreciated!
Client code:
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");
}
}
}
}
}
Server Code:
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);
}
}
}