0

I'm writing a class library on UWP platform that is going to be used from a mobile UWP application.

The library needs to talk with an external device through a proprietary protocol TCP-based. The protocol requires Receive or Send operation to be waited for an exact amount of time.

I've actually implemented the communication layer with ReceiveAsync and SendAsync, "await"ing for them, as the TPL pattern suggets.

After a lot of reading on the argument, I discover there's no way to set natively a timeout on read/write operations. Some tricks can be used to implement the timeout process (es: .WaitAny or timeoutable tokens) but all my readings brings me to this fact:

A ReceiveAsync or SendAsync task can be interrupted only closing the socket

My question is: is this true? A timeout'd Receive/Send can be blocked only closing/disposing the socket?

If this is true, as the protocol I'm implementing doesn't allow me to open/close the socket hundreds of time, I need to revert back to the sync Receive/Send version of the command that actually handle graceful timeout.

I have read a lot on the arguments and I'm quite sure of what I have written, but honestly I hope there's a way to handle the timeout using the TPL pattern without needing to close the socket...

Thanks.

Yusef Maali
  • 2,201
  • 2
  • 23
  • 29

1 Answers1

1

My question is: is this true? A timeout'd Receive/Send can be blocked only closing/disposing the socket?

Yes, that is correct. Timeouts don't apply to asynchronous socket methods. The proper way to cancel an existing async read/write is to close the socket.

If this is true, as the protocol I'm implementing doesn't allow me to open/close the socket hundreds of time, I need to revert back to the sync Receive/Send version of the command that actually handle graceful timeout.

I disagree. Timeouts in protocol definitions are only advisory; they cannot be enforced. Or put another way, it doesn't have to be a literal Receive or Send timeout; it can be a logical "receive" or "send" timeout.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Thanks for your reply. I agree with you timeouts are advisory but not in this case. The protocol I'm working on is build on top of very cheap hardware devices (I'd like to say IoT). The device due to protocol version inconsistency or hardware issue or other external events, may _not_ reply to my request, discarding it without replying with a NACK or some other error status. In this case the protocol needs me to fire a timeout and to try to recover. This is the typical situation in which the communication protocol has _not_ been built by software engineer and makes stuff a bit complicated. – Yusef Maali Sep 16 '17 at 10:42
  • That's fine. A socket "send" completes *when the bytes are transferred to the OS TCP/IP stack* - they may not have even been sent to the network yet. It certainly is not a timeout for a reply. So applying a timeout on the synchronous send wouldn't work anyway. You need "logical" timeouts as stated in my answer, which are equally achievable with synchronous and asynchronous socket APIs. – Stephen Cleary Sep 16 '17 at 16:22
  • What are logical timeouts? Are you talking about having non-blocking reads and counting the amount of time the reads returns 0 bytes? This may be a nice solution. – Yusef Maali Sep 17 '17 at 09:58
  • No. A read won't return 0 bytes until the socket is closed on the other side. I would have a read constantly going, and then define a logical "command" operation that represents a command sent and a response received. This "command" is the operation that times out, not the socket writes and reads. So its timeout would be governed by a `Task.Delay` or `CancellationTokenSource.CancelAfter`, not an actual socket read/write timeout. – Stephen Cleary Sep 17 '17 at 16:17