So i'm using tidhttp to make post requests. when i try to set connectTimeout whatever period of time it has no effect. I still wait ~5 sec before i get exception.
Thanks in advance!
If you are connecting to a hostname instead of an IP address, the hostname has to be resolved to an IP via a DNS lookup, which can take time, especially if the hostname has not been cached by the OS yet. The ConnectTimeout property does not account for that time.
Also, when ConnectTimeout is not zero, or if TIdAntiFreeze is being used, Indy has to use an internal worker thread to perform the actual socket API connect() call to the server. Starting a new thread can take some time, depending on available system resources at that moment. ConnectTimeout does not account for that time, either.
The current implementation of ConnectTimeout applies only to the actual socket API connect() call itself, not to any of the extra work needed to reach that point. As such, if you have a 5 second ConnectTimeout value set, it is possible to hanve more than 5 seconds elapse before TIdTCPClient.Connect() exits.
Related
I want to download a file from FTP. If the file is small (usually under 1000MB) it works. However, if the file is big I get an EIdReadTimeout. Why? Should I keep the connection alive? From what I know reading data has its own channel so I don't have to keep the connection alive.
What is odd is that the exception appears at the end of the Get (after Get successfully downloads the whole file): FTP.Get(Name, TempGzFile, TRUE, FALSE) !!!!
Documentation:
TIdFTP.ReadTimeout - Number of milliseconds to wait for an FTP protocol response.
TIdFTP.TransferTimeout - Timeout value for read operations on the data channel for the FTP
client.
By default ReadTimeout is set to 60sec and TransferTimeout to 10sec.
I a using Delphi XE7 (which I guess uses Indy 10). The Passive property for my IdFTP is set to false.
The FTP protocol uses multiple TCP/IP connections - one for the main command/response connection, and separate connections for data transfers. While a data transfer is in progress, the main command connection sits idle. Once the transfer is finished, the command connection receives a response.
If you are passing through a router/firewall that is not FTP-aware, the command connection is likely to get killed if it sits idle for too long during a large transfer. The connection is usually not killed "gracefully", so even the OS does not know the connection is gone. When TIdFTP then tries to read a transfer response that never arrives, it times out.
To account for that, use the TIdFTP.NATKeepAlive property to enable TCP/IP level keep-alives on the command connection during transfers. Set NATKeepAlive.UseKeepAlive to True, and set NATKeepAlive.IdleTimeMS (the idle timeout before keepalives start sending) and NATKeepAlive.IntervalMS (the interval between each keepalive) to suitable values.
Note, however, that IdleTimeMS and IntervalMS are only implemented for Windows 2000+, Linux, and BSD at this time. Other platforms use defaults provided by the OS (which tend to be very large). If you need to customize the values on those platforms, you can use the TIdFTP.OnDataChannelCreate and TIdFTP.OnDataChannelDestroy events to call TIdFTP.Socket.Binding.SetSocketOption() directly as needed.
If a connection is 'inactive' I guess the Weblogic internal data source manager should recover the connection. Why should 'Inactive Connection Timeout' be a configurable parameter. Is there any use case which requires WL to wait for certain period before an inactive connection is recovered?
Thanks in advance.
This variation could occur depending on what downstream systems are doing, or where a system is sometimes under load and not able to respond in an adequate period of time
A leaked connection is a connection that was not properly returned to the connection pool in the data source. To automatically recover leaked connections, you can specify a value for Inactive Connection Timeout on the JDBC Data Source. ( Configuration: Connection Pool page in the Administration Console.) When you set a value for Inactive Connection Timeout, WebLogic Server forcibly returns a connection to the data source when there is no activity on a reserved connection for the number of seconds that you specify. When set to 0 (the default value), this feature is turned off.
After digging into this.. specific to question "Why should it be configurable..", because by default this feature is turned off, you can turn it on if you believe that the application for some reason is not returning connections back to the pool, i.e.
leaking connections. Depending on the application use cases and the amount of resource leakage, one could set the duration. IOW, you don't want to timeout connections too quickly, because it will force the app server to have to recreate those on next need or cause unnecessary errors. But if the application is leaking a lot of connections, then you can tighten the duration so it keeps cleaning up.
I have a Windows Service that works with an advantage database and occasionally makes some http calls. On rare occasions these calls can be very long. To the tune that my database connection times out. I'm not using a Data Module or anything. Just creating the connection manually.
My primary question is what usually prevents the connection from timing out if I just haven't used it in a while? Do the TAdsComponents send a keep alive message that gets called in the background somehow? Is that dependent on the vcl so I don't have that in my service? Somehow I feel like creating a thread to make my http call, and in the main thread checking for it to finish every few seconds would prevent the connection from dying. Is that ever true?
Yes, there is a keepalive mechanism as you expect. The client (for all communication types, TCP, UDP, Shared memory) sends a "ping" to the server every so often to let the server know that connection is still alive. The frequency of that keepalive ping is based on the server configuration parameter CLIENT_TIMEOUT. With the default settings, I believe the keepalive ping is sent every 30 seconds.
The keepalive logic runs in a separate thread that is started by the code that handles the communication. In other words, it does not depend on any of the VCL components; if you have a connection to the server, then that thread should be running.
One way to check if your connections are timing out is to look in the Advantage error log. There should be 7020 errors corresponding to timed out connections.
Some things that come to mind that might result in timed out connections include:
The client process being suspended for some reason so that the keepalive thread could not run. This seems unlikely.
The keepalive thread was killed for some reason. This also seems unlikely; you would have to go out of your way to make this happen.
A firewall may close the connection if there is no activity for a time. I would think, though, that a 30 second interval would be sufficient to prevent that.
A firewall may disallow the UDP keepalive packets. Firewalls, by nature, are "suspicious" of UDP packets. You might make sure you are using TCP/IP.
I developped an application that uses indy component to download updates from a remote server.
The problem is that if the FTP server is down or the IP address is not correct, the idFTP.connect() takes too long to give the result (connection failure).
What is the best way to accelerate the connection answer, or may be checking ip address before connection to idFTP.
Thanks in advance.
You should set ReadTimeout property, by default it is set to one minute.
By default, Indy clients wait as long as it takes for the OS to report whether the connection was successful or not. Yes, that can take a long time, if the OS has to look up the hostname with DNS, do network checks, deal with network latency, etc. If you do not want to wait that long, you can use the Timeout parameter of Connect() in Indy 9 and earlier, or the ConnectTimeout property in Indy 10, to reduce the amount of time waited on. HOWEVER, that only applies to the actual socket connect attempt once the server IP has been determined. If you set the Host property to a non-IP hostname, Indy asks the OS to perform a DNS lookup to get the hostname's IP, and there is no logic available in Connect() to control the time it takes to do that lookup. If you need that much control, then use TIdDNSResolver to get the IP manually and then assign it to the Host property before calling Connect().
Well, native connect() API timeouts are notoriously lengthy by design, (to accommodate high latency links like modems). Artificially shortening the timeout may result in premature failure notification, (though as many developers have never seen a modem, it's not that much of a problem today:).
FTP is a reasonably complex transfer requiring two TCP connections and perhaps a DNS lookup - any of these could conceivably generate long connection delays. TidFTP has an inherited 'ReadTimeout' property and a connect() overload with a timeout parameter, but I'm not sure how effective they are.
Historically, I have always timed out such operations myself using a TTimer or similar - if the FTP thread does not respond with a suitable signal, (eg. TThread.Sychronize or user-defined Windows message SendMessage()'d to the GUI), in time, a 'FTP failed' actions are taken and a flag is set in the FTP thread that tells it to ignore any replies and self-terminate. Don't use PostMessage - if you do, there is a small window of time in which a posted response my be queued up while the TTimer is firing - a race.
Oh - and if you are just plonking a TidFTP onto the form, (or creating one in TForm.FormCreate), and trying to run it from the main GUI thread, (with, or without, TidAntiFreeze), stop doing it and thread off the FTP.
I am building a "test" button to verify SMTP configuration in an app.
If the user types in an incorrect port number, switches SSL on/off to the incorrect state, or types in a valid domain name, but one that isn't hosting an SMTP server, the app hangs, waiting for a timeout.
Basically, it found a server, but is unable to connect to the specified port.
This timeout seems to be about 1 minute 15 seconds in this case.
I tried setting the timeout like this:
var client = new SmtpClient(hostname, port);
client.Timeout = 15000; // milliseconds
but the timeout is still around 1 minute 15 seconds.
Is there anything else I need to configure?
Note that while I can use "SendAsync" to avoid the hang, I still want to use a bit lower timeout in this case.
This could be related to DNS resolution which is done synchronously. You can confirm this easily by using an IP address, instead of a host name, and see if the timeout gets closer to the expected 15 seconds.
If that's the case then a possible alternative, that I have not tested under iOS, could be to use Mono.Dns.