I am new in http connections. The thing I want to realize is that the server should send some data (notifications) to the client periodically by persistent connection.
I wrote a code in server side by php like:
<?php
set_time_limit(0);
header('Connection: keep-alive');
$i = 0;
while($i < 10){
echo "Hello$i<br/>";
sleep(5);
$i++;
}
?>
and tried to connect to the server by java:
public static void main(String[] args) throws Exception {
URL oracle = new URL("http://localhost/connection.php");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
I expected to get content from the server every five seconds like following:
Hello0<br/>
Hello1<br/>
...
but instead of this the java client is waiting 50 seconds. and printing:
Hello0<br/>Hello1<br/>Hello2<br/>Hello3<br/>Hello4<br/>Hello5<br/>Hello6<br/>Hello7<br/>Hello8<br/>Hello9<br/>
I want the server send notifications itself. instead of the client connect to the server every five seconds.
It's really unnecessary to add Connection: keep-alive header in response for HTTP/1.1 server, UNLESS for backward compatibility.
No matter how long or many times you sleep in that loop, it's seen as ONE request by the client nevertheless.
with that being said, your client snippet, in fact, only make ONE request to http://localhost/connection.php, and it's impossible to reuse URLConnection in order to dispatch another request(achieving persistent).
to sum up:
Persistent Connection behaviour is handled at transport layer (TCP), more specifically, you are required to reuse a client socket for multiple request to the same host plus some other requirements specified in HTTP/1.1.
Go and find some projects that are suitable for your needs, don't reinvent the wheel.
Flushing the connections seemed really good idea. But I think I found better solution. Instead of keeping connection with unlimited timeout, I think it is better to make persistent connection with 5 (N minutes) minutes timeout. It is better because when the user will be offline unexpectedly, the server will keep the connection alive anyway. and it is not good. That's why I am going to make 5 (this number is optional) connections for notification. That is the server will use first one for notification and closes the connection after sending request, and the rest 4 connections will be on duty. When the client (or java client) will receive the notification, it will make new connection to fill missing part or the connection times out.
and the client will be notified immediately every time (of course if connected to the internet).
If someone has better solution I will be happy to see that.
Here is my code :
URL u = new URL("http://www.google.com");
URLConnection conn = u.openConnection();
conn.setConnectTimeout(3000);
conn.connect();
My network connection is sometimes unstable(I've connected to the wireless router but actually my router doesn't have Internet access). When that happens, this code will block for a lone time and finally throws UnknownHostException. Why setConnectTimeout(3000) doesn't work in this case? How to fix this?
Thanks!
------------update---------------
My guess is that conn.connect() will query DNS first but there's no time limit for this operation. I've tried Socket class and problem remains. setTimeout() seems do not work for DNS query.
I found a post that can work around it. Use another thread to query DNS to simulate timeout:
http://thushw.blogspot.sg/2009/11/resolving-domain-names-quickly-with.html
Some non-standard implmentation of this method may ignore the specified timeout.
See this setConnectTimeout
Note: expressed in Scala. Using a BufferedReader to process a gzipped HTTP stream and iterating through each line to read the incoming data. Problem is that if there is ever a reset connection due to a network I/O issue (provider does weird things sometimes) then I can see the connection staying open for up to 15 seconds before it times out, something I'd like to get down to 1 second. For some reason our office provider resets connections every 11 hours.
Here's how I'm handling the connection:
val connection = getConnection(URL, USER, PASSWORD)
val inputStream = connection.getInputStream()
val reader = new BufferedReader(new InputStreamReader(new StreamingGZIPInputStream(inputStream), GNIP_CHARSET))
var line = reader.readLine()
while(line != null){
parseSupervisor ! ParseThis(line)
line = reader.readLine()
}
throw new ParseStreamCollapseException
and here is getConnection defined:
private def getConnection(urlString: String, user: String, password: String): HttpURLConnection = {
val url = new URL(urlString)
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setReadTimeout(1000 * KEEPALIVE_TIMEOUT)
connection.setConnectTimeout(1000 * 1)
connection.setRequestProperty("Authorization", createAuthHeader(user, password));
connection.setRequestProperty("Accept-Encoding", "gzip")
connection
}
To summarize: reading HTTP stream line-by-line via java.io.BufferedReader. Keep-alive on stream is 16 seconds, but to prevent further data loss I'd like to narrow it down to hopefully 1-2 seconds (basically check if stream is currently blank or if is network I/O). Some device in the middle is terminating the connection every 11 hours, and it would be nice to have a meaningful workaround to minimize data loss. The HttpURLConnection does not receive a "termination signal" on the connection.
Thanks!
Unfortunately, unless the network device that's killing the connection is closing it cleanly, you're not going to get any sort of notification that the connection is dead. The reason for this is that there is no way to tell the difference between a remote host that is just taking a long time to respond and a broken connection. Either way the socket is silent.
Again, assuming that the connection is just being severed, your only option to detect the broken connection more quickly is to decrease your timeout.
I'm running into an issue when i try to use the HttpClient connecting
to a url. The http connection is taking a longer time to timeout, even after i set
a connection timeoout.
int timeoutConnection = 5000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
It works perfect most of the time. However, every once in while, the http connection runs for ever and ignore the setconnectiontimeout, especailly when the phone is connected to wifi, and the phone was idling.
So after the phone is idling, the first time i try to connect, the http connection ignores the setconnectiontimeout and runs forever, after i cancel it and try again, it works like charm everytime. But that one time that doesn't work it creates a threadtimeout error, i tried using a different thread, it works, but i know that the thread is running for long time.
I understand that the wifi goes to sleep on idle, but i dont understand why its ignoring the setconnectiontimeout.
Anyone can help, id really appreciated.
Not sure if this helps you, however I think it's worth sharing here. While playing with the timeout stuff I found there is a third timeout type you can assign:
// the timeout until a connection is established
private static final int CONNECTION_TIMEOUT = 5000; /* 5 seconds */
// the timeout for waiting for data
private static final int SOCKET_TIMEOUT = 5000; /* 5 seconds */
// ----------- this is the one I am talking about:
// the timeout until a ManagedClientConnection is got
// from ClientConnectionRequest
private static final long MCC_TIMEOUT = 5000; /* 5 seconds */
...
HttpGet httpGet = new HttpGet(url);
setTimeouts(httpGet.getParams());
...
private static void setTimeouts(HttpParams params) {
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
CONNECTION_TIMEOUT);
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
params.setLongParameter(ConnManagerPNames.TIMEOUT, MCC_TIMEOUT);
}
I've met the same problem, I guess maybe the Android doesn't support this parameter.
In my case i tested all three parameters for the ThreadSafeClientConnManager
params.setParameter( ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(20) );
params.setIntParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 200 );
params.setLongParameter( ConnManagerPNames.TIMEOUT, 10 );
ThreadSafeClientConnManager connmgr = new ThreadSafeClientConnManager( params );
The first and second worked fine, but the third didn't work as documented. No exception was thrown and the executing thread was blocked indefinitely when the DefaultHttpClient#execute() was executing.
see http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e650
"...One can ensure the connection manager does not block indefinitely in the connection request operation by setting 'http.conn-manager.timeout' to a positive value. If the connection request cannot be serviced within the given time period ConnectionPoolTimeoutException will be thrown."
Thread t=new Thread()
{
public void run()
{
try
{
Thread.sleep(absolutetimeout);
httpclient.getConnectionManager().closeExpiredConnections();
httpclient.getConnectionManager().closeIdleConnections(absolutetimeout,TimeUnit.MILLISECONDS);
httpclient.getConnectionManager().shutdown();
log.debug("We shutdown the connection manager!");
}
catch(InterruptedException e)
{}
}
};
t.start();
HttpResponse res= httpclient.execute(httpget);
t.interrupt();
Is that along the lines of what you all are suggesting?
I'm not exactly sure how to cancel the execute once it has started, but this seemed to work for me. I'm not sure which of the three lines in the thread did the magic, or if it was some combination of all of them.
You could manage the timeouts yourself, this way you can be confident that no matter what state the connection gets in, unless you receive an acceptable response, that your timeout will fire and the http request will be aborted.
I've had similar issues with timeouts on android. To resolve it what I did was used the commands to not let the phone idle while I was attempting to establish a connection and during any reads or writes to the connection. Its probably worth a shot in this case as well.
Although I haven't seen this on the Android platform, I've seen similar things on other platforms and the solution in these cases is to manage the timeout yourself. Kick off another thread (the timeout thread) when your make your request. The timeout thread counts down the requisite time. If the timeout expires before you receive any data, the timeout thread cancels the original request and you retry with a new request. Harder to code, but at least you know it will work.
From you snippet it's not ultimately clear if you set the timeouts before calling HttpClient.executeMethod(..). So this is my guess.
Well, if you idle/multitask to another application, then your thread that is running might be stopped and destroyed. Maybe you should put the connection code inside a Service instead?:
http://developer.android.com/reference/android/os/AsyncTask.html
http://developer.android.com/reference/android/app/IntentService.html
How are you making the HTTP Connection? This looks like a threading issue. If you are using a background thread, then the thread may be killed along with any timeout registered. The fact that it works the next time tells me that your code will work, if you make the call in a android component and manage the WAKE_LOCK on it yourself. Anyways please post more information about the calling mechanism?
The problem might be in the Apache HTTP Client. See HTTPCLIENT-1098.
Fixed in 4.1.2.
The timeout exception tries to reverse DNS the IP, for logging purposes. This takes an additional time until the exception is actually fired.
I am new in Apache HttpClient, I used the following code to get the HTTP connection timeout (disconnected) after certain time interval:
PostMethod method = new PostMethod(authURL);
HttpClient client = new HttpClient();
HttpClientParams params= new HttpClientParams();
params.setParameter(params.CONNECTION_MANAGER_TIMEOUT, 10); //10 Nano second
client.executeMethod(method);
but it wait for more than one minute without any hope to timeout/disconnect? Where can the problem be?
There are 2 timeouts involved in HTTPClient, try to set both,
client.getHttpConnectionManager().
getParams().setConnectionTimeout(5000);
client.getHttpConnectionManager().
getParams().setSoTimeout(5000);
However, the values will be ignored if the connection is stuck in a native socket call. So you might have to run the request in a different thread so you can time it out. See my answer to this question on how to do that,
java native Process timeout
The connection manager timeout triggers when the act of trying to get a connection from your connection manager takes too long. This is not the same as the timeout for the http connection itself. Use HttpClientParams.setSoTimeout() instead.
http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/params/HttpMethodParams.html#setSoTimeout%28int%29
Have you looked at setting SO_TIMEOUT ?
Sets the socket timeout (SO_TIMEOUT)
in milliseconds to be used when
executing the method. A timeout value
of zero is interpreted as an infinite
timeout.