0
votes

I have tried the following cases and used a stopwatch to mesaure the actual time it takes for the socket to receive. Note that the timeouts are in miliseconds.

Dim NextClient As New TcpClient
NextClient.ReceiveTimeout = 1 //Case 1
NextClient.Client.ReceiveTimeout = 1 //Case 2
Dim ns As Net.Sockets.NetworkStream = client.GetStream()
ns.ReadTimeout = 1 //Case 3
Dim sw As New Stopwatch
sw.Start()
ns.Read(gbytes, 0, 5997)
sw.Stop()

BTW, ns.CanTimeout returns true. Also, I am not really expecting a 1 ms precision and it is only for testing purposes. I have actually started with 500 ms but first wanted to test with this.

In all cases and their combinations, even though the I have measured 100+ miliseconds each time with the stopwatch, I receive the data with no exceptions. If I intentionally delay the response over few seconds, however, I can get the exception. But even my ping / 2 to the server is much more than 1 ms.

Oddly, if I set the timeout to 1000 ms and the server response takes about 1020 ms the exception is triggered.

So, is there a minimum value or something else?

2

2 Answers

1
votes

MSDN:

The ReceiveTimeout property determines the amount of time that the Read method will block until it is able to receive data. This time is measured in milliseconds. If the time-out expires before Read successfully completes, TcpClient throws a IOException. There is no time-out by default.

... if I set the timeout to 1000 ms and the server response takes about 1020 ms the exception is triggered. Well, if the response takes longer than the configured timeout, you'll get the exception.

If the time-out period is exceeded, the Receive method will throw a SocketException.

... is there a minimum value or something else?

Applicable values vary from -1 over 0 to MAX_INT_32.

The time-out value, in milliseconds. The default value is 0, which indicates an infinite time-out period. Specifying -1 also indicates an infinite time-out period.

However, the underlying Hardware and/or OS determines the resultion/granularity of the timeout (e.g. Windows has typically a default timer resolution of 15.625 ms. Consequently, exceptions are only raised at multiples of 15.625 ms).

0
votes

The definition from Microsoft appears to be here: https://msdn.microsoft.com/en-us/library/bk6w7hs8%28v=vs.110%29.aspx

and the remark against it reads:

"If the read operation does not complete within the time specified by this property, the read operation throws an IOException."

So the issue is somewhat complicated because, as usual, it relies on the wording being written accurately and distinctly.

The definition makes no reference to any kind of timer quanta or limitations of any timer, therefore if you specify a timeout of 1000mS and a read is not received within 1000mS then an exception must be thrown otherwise the mechanism is not compliant with its definition.

To make it correct any definition would have to specify some value of timer accuracy otherwise there is no workable definition of 'exceeds'. Just because the timeout is specified as an integer doesn't mean the interval is exceeded after 1001mS - you could justifiably say it's exceeded after 1000.0000000000000001ms.

There is also no definition of 'complete' when it states "If the read operation does not complete...".

Does it mean if it hasn't read ALL the bytes you asked for, or, if you ask for a partial read, does it mean if it hasn't read anything?

It's just not worded very well, and I suspect that Microsoft would say that the definition is wrong rather that the function being wrong, which doesn't help you much because they could change the way the function worked between releases in a way that might break your code without even commenting on it.

Provided it still does what the description says then it still works according to spec, and if you use features that are 'undocumented' - in other words things you observe that it does rather than things that the specification says it does - then that's just tough.

Unfortunately this simply doesn't do what the spec says in the first place, so all you can do is to use and exploit its 'observed behaviour' and hope that it stays the same.