Home > Blockchain >  Understanding Indy Socket timeouts
Understanding Indy Socket timeouts

Time:11-29

I want to understand how Indy socket timeouts works, because I want to use them in the following way.

I have an application (TCP server/client) that transfers a file over the Internet. When I start the transfer, I want to be able to stop it fast enough (let's say, 1500 ms) if I decide that. If some socket is reading data, and something happens on the wire that makes it late, I won't be able to stop the transfer, because the socket is hung reading data. So I need to set some short timeouts, that in normal operation will not be triggered. But if something happens and data is running late, the control will be passed to the main proc and I'll be able to check for the abort request.

Now, I don't know what to do next... If a socket read times out, what do that mean? The socket did not receive any data for that period of time... Or, the socket received some data in the buffer but doesn't have time to finish? I have a feeling that those timeouts are the waiting periods for something to happen (start a read or a write operation). But (let's say a read), once started, what happens if the socket receives half of the data (which he was asked to read) and then nothing comes? Will that call block the program execution forever? Because if that happens, then again I will not be able to check for abort request.

Anyway... when the timeout occurs, it will raise an exception? I can catch it and try again, in the same connection, like nothing happened? Will the in/out buffer be modified after a timeout?

I am using this to set the Read and Write timeouts:

Socket.ReadTimeout:= WorkingRTimeOut;
Socket.Binding.SetSockOpt(SOL_SOCKET, SO_SNDTIMEO, WorkingWTimeOut);

CodePudding user response:

Socket timeouts are applied on a per-byte basis.

If you ask a socket to read N number of bytes, it will return as many bytes as it can, up to N bytes max, from the socket's receive buffer. It can (and frequently does) return fewer bytes, requiring another read to receive the remaining bytes. If a timeout error occurs, it means no bytes at all arrived in time for the current read. There is no way to know why, or whether they ever will arrive.

If you ask a socket to send N number of bytes, it will accept as many bytes as it can, up to N bytes max, into the socket's write buffer. It can (and sometimes does) buffer fewer bytes, requiring another send to buffer the remaining bytes. If a timeout occurs, it means the socket's write buffer has filled up, the receiver is not reading fast enough (or at all) to clear space in the sender's write buffer in time.

If you ask Indy to read/send N number of bytes, it may perform multiple socket reads/sends internally, waiting for all of the expected bytes to be received/sent. So it may have read/sent X number of bytes, where X < N, before the timeout occured. Sure, you could try another read/send again, asking for only the remaining bytes you haven't received/sent yet (N - X), but don't ask for the bytes you already received/sent (X). You might receive/send more bytes, or you might get another timeout, there is no way to know until you try. However, depending on context, it may not be easy/possible to know how many bytes were received/sent before the timeout, so you might not know how many remaining bytes to ask for again. In which case, about all you can sensibly do is just close the TCP connection, reconnect, and resume/start over.

As for your ability to abort a connection quickly, you could move your read/send code to a worker thread, and then Disconnect() the socket from your main proc when needed. That will generally abort any blocking read/send in progress.

  • Related