As we know, we can abort any TIdTCPConnection child classes in the OnWork event, including the TidImap4 client component.
But how to abort the connection before the timeout value is reached?
Thanks.
(11-14-2018, 05:56 AM)edwinyzh Wrote: [ -> ]how to abort the connection before the timeout value is reached?
Several events are triggered by
TIdTCPClient.Connect() (in this order):
-
OnBeforeBind
-
OnSocketAllocated
-
OnAfterBind
-
OnStatus(hsResolving) ¹
-
OnStatus(hsConnecting) ²
-
OnStatus(hsConnected)
-
OnConnected
You can raise an exception from any of those events.
¹ during the
hsResolving stage, there is currently no way to abort a hostname lookup. You just have to let it play out on its own. Otherwise, do your own lookup, such as via
TIdDNSResolver, and assign only IP addresses to
TIdTCPClient.
² The
ConnectTimeout properly applies to the
hsConnecting stage only. During that stage, to abort the connection prematurely, you must close the underlying socket directly (which is what
Connect() does when the timeout elapses). You can close the socket at any time after the
OnSocketAllocated event has been triggered, such as by calling
TIdTCPClient.Socket.Binding.CloseSocket() ³.
³ I suppose calling
TIdTCPClient.Disconnect() would also work, though it does
Close() the
IOHandler (which has threading issues for
TIdSSLIOHandlerSocketOpenSSL), and it also triggers the
OnStatus(hsDisconnecting),
OnDisconnected, and
OnStatus(hsDisconnected) events. I think for purposes of aborting a connection in progress, using
CloseSocket() would be a safer choice.
rlebeau,
Thanks for the help info.
I just browsed the Indy source code, it seems that the uninterruptible time range is in between OnStatus(hsConnecting) and OnStatus(hsConnected), where you have no way to abort until the timeout's reached?
It seems that there is no other way except using a smaller timeout value.
(11-15-2018, 04:36 AM)edwinyzh Wrote: [ -> ]I just browsed the Indy source code, it seems that the uninterruptible time range is in between OnStatus(hsConnecting) and OnStatus(hsConnected), where you have no way to abort until the timeout's reached?
That is not true. As I already explained in my previous reply, that time range IS interruptible. You just need to close the underlying socket itself to do so.
Between
hsConnecting and
hsConnected is when Indy is making the actual connection to the server (and is the only time when
ConnectTimeout takes effect). If the socket is closed before the underlying socket API
connect() is called, the connection fails with an "invalid socket" error. If the socket API
connect() is already in progress when the socket is closed, the connection gets aborted with an appropriate error. Either way, the end result is the same - the API
connect() fails, the connecting thread gets terminated, and
TIdTCPClient.Connect() sees that and raises an exception into your code (typically
EIdSocketError or
EIdConnectException).
The only time range that IS NOT interruptible is between
hsResolving and
hsConnecting, when
Connect() is blocked on the OS performing a DNS lookup, and
ConnectTimeout has no effect.