I am trying to terminate a connection if no data is being received or server is just keeping the connection open for a url by setting connectionTimeout and readTimeout.
I have create anonymous class of URLResource and fetch the data from url. code block below is of spring project. spring boot version is 2.7.1
try {
URL url = new URL("http://httpstat.us/200?sleep=20000");
UrlResource urlResource = new UrlResource(url) {
#Override
protected void customizeConnection(HttpURLConnection connection) throws IOException {
super.customizeConnection(connection);
connection.setConnectTimeout(4000);
connection.setReadTimeout(2000);
}
};
InputStream inputStream = urlResource.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream,
StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
br.lines().forEach(line -> System.out.println(line));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
System.out.println("IO exception");
e.printStackTrace();
}
I am using a service (http://httpstat.us/200?sleep=20000) that allows to hold connection for specified amount of time to check out the connection termination but the connection is not getting terminate after specified amount of time
Is there any other way to customize urlResource so that timeout can be set
It looks like the UrlResource.getInputStream() is missing to call customizeConnection(con); in its logic:
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
try {
return con.getInputStream();
}
catch (IOException ex) {
// Close the HTTP connection (if applicable).
if (con instanceof HttpURLConnection httpConn) {
httpConn.disconnect();
}
throw ex;
}
}
Please, raise a GH issue for Spring Framework to address this problem.
As a workaround I see this:
UrlResource urlResource = new UrlResource(url) {
#Override
public InputStream getInputStream() throws IOException {
URLConnection con = getURL().openConnection();
customizeConnection(con);
try {
return con.getInputStream();
}
catch (IOException ex) {
// Close the HTTP connection (if applicable).
if (con instanceof HttpURLConnection httpConn) {
httpConn.disconnect();
}
throw ex;
}
}
#Override
protected void customizeConnection(HttpURLConnection connection) throws IOException {
super.customizeConnection(connection);
connection.setReadTimeout(2000);
}
};
So, I override that getInputStream() with the same logic, but also apply our customizeConnection() on it. With that fix your test fails like this:
java.net.SocketTimeoutException: Read timed out
at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:283)
at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:309)
at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350)
at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803)
at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966)
at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:244)
at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:343)
at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:791)
at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:726)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1688)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589)
Related
In the logcat I get a warning:
W/System: A resource failed to call end.
I am 100% positive that this piece of code makes the warning, since when I take it out it stops.
I can't seem to fix it so it doesn't display warning.
The purpose of the code is to check if there is internet connection or not.
It is on separate thread. Declared with:
public class ConnectWifiThread extends Thread {
public static boolean isInternetAvailable(Context context) {
Here is the code:
try {
URL url = new URL("https://www.google.com/");
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setRequestProperty("User-Agent", "test");
https.setRequestProperty("Connection", "close");
https.setConnectTimeout(2000); // mTimeout is in seconds
https.connect();
int tempResponse = https.getResponseCode();
if (tempResponse == 200) {
https.disconnect();
Thread.sleep(50);
https=null;
url=null;
Thread.sleep(50);
Log.d("Has", "internet");
return true;
} else {
https.disconnect();
Thread.sleep(50);
https=null;
url=null;
Thread.sleep(50);
Log.d("NO", "internet");
return false;
}
} catch (MalformedURLException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
catch (Exception e) {
Log.d("Error checking internet", e.getMessage());
return false;
}
Thank you
When you use a URLConnection, by default it makes an input stream for you to read the response. You'd get that by calling getInputStream() on the connection, and then you'd read the stream to completion and close it.
If you don't need the data, you can alternatively call setDoInput(false) to save you the trouble of doing the above.
I've seen In several answers here, in order to reuse connection, I needed to close inputstream and outputstream.
Before I closed the streams, I had seen too many CLOSE_WAIT connections.
But now, In case of a base response (for instance 404 file not found)
I'm handling the response this way
public static void handleIOError(URLConnection conn)
{
InputStream es = null;
HttpURLConnection urlConn = null;
if (conn instanceof HttpURLConnection)
{
urlConn = (HttpURLConnection)conn;
es = urlConn.getErrorStream();
}
if (es != null)
{
try
{
while (es.read() > -1) {}
}
catch (IOException e)
{
logger.error("Unable to close input stream", e);
}
finally
{
IOUtils.closeQuietly(es);
}
}
}
so I'm closing inputstream, but still, I'm having multiple CLOSE_WAIT connections. I'm guessing I didn't close the socket stream, but which one? As you may know, in case of an error I can not do urlConn.getInputStream()
my server is tomcat 8.
Any Idea how to solve the socket leak?
I have a class called RetreiveHttpStringResponse. It's used to get an InputStream from an URL containing JSON data. The class extends AsyncTask<String, Void, InputStream>. So the strange problem here is that null is always returned. No matter what. There is even no Exception. I checked out the program behaviour with the debugger and could see that at point (1) the processing is jumping immediately to the finally-statement and continues with return null;. And again there are no Errors and no Exceptions are going on. The programm is running normally.
I'm using Android 4.4 (SDK version 19), the response code is 200 and the following lines are set in the Manifest file.
uses-permission android:name="android.permission.INTERNET"
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"
The problem is happening on the emulator and on a real device with internet connection. Here is the code:
#Override
protected InputStream doInBackground(String... arg0) {
URL url = null;
InputStream is = null;
HttpURLConnection urlConn = null;
int responseCode = 0;
try {
url = new URL(arg0[0]);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setReadTimeout(10000);
urlConn.setConnectTimeout(15000);
urlConn.setRequestMethod("GET");
urlConn.connect();
responseCode = urlConn.getResponseCode();
Log.d("DataHandlerInternet:RESPONSE_CODE", "The response is: " + responseCode);
is= urlConn.getInputStream(); //-->(1)<--
return is;
}
catch ( MalformedURLException e ) { // new URL() went wrong!
//TODO error message. URL is not correct!
e.printStackTrace();
}
catch (SocketTimeoutException e) { // Timeout while connecting or holding connection to URL.
//TODO error message. Timeout happened!
e.printStackTrace();
}
catch ( IOException e ) { // openConnection() failed!
//TODO error message. Couldn't connect to URL!
e.printStackTrace();
}
catch( Exception e ) { // Any other Exception!
e.printStackTrace();
}
finally {
try { if(is != null) { is.close(); } } catch(Exception e) {e.printStackTrace();}
try { if(urlConn != null) { urlConn.disconnect(); } } catch(Exception e) {e.printStackTrace();}
}
return null;
}
One bad solution is to delete the finally-statement. Well, not the best way to solve this problem.
Now I changed the code. I've put the reading in it and return just the String.
#Override
protected String doInBackground(String... arg0) {
URL url = null;
InputStream is = null;
HttpURLConnection urlConn = null;
int responseCode = 0;
try {
url = new URL(arg0[0]);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setReadTimeout(10000);
urlConn.setConnectTimeout(15000);
urlConn.setRequestMethod("GET");
urlConn.connect();
responseCode = urlConn.getResponseCode();
Log.d("DataHandlerInternet:RESPONSE_CODE", "The response is: " + responseCode);
is= urlConn.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while ( (line = br.readLine()) != null ) {
sb.append(line);
}
return sb.toString();
}
catch ( MalformedURLException e ) { // new URL() went wrong!
//TODO error message. URL is not correct!
e.printStackTrace();
}
catch (SocketTimeoutException e) { // Timeout while connecting or holding connection to URL.
//TODO error message. Timeout happened!
e.printStackTrace();
}
catch ( IOException e ) { // openConnection() failed!
//TODO error message. Couldn't connect to URL!
e.printStackTrace();
}
catch( Exception e ) { // Any other Exception!
e.printStackTrace();
}
finally {
try { if(is != null) { is.close(); } } catch(Exception e) {e.printStackTrace();}
try { if(urlConn != null) { urlConn.disconnect(); } } catch(Exception e) {e.printStackTrace();}
}
return null;
}
And still, after going through the while loop the return line; is completely ignored. I've checked the data in the String with the debugger and it was correct! No Errors no Exceptions.
finally will run in either case, also during normal return without exceptions. And you call .close in the finally statement clause.
So your code always returns the closed stream. Probably this is not that you intend.
Your description ("jumps to finally statement") still looks very much like a exception has been thrown by urlConn.getInputStream(). Strange you do not observe it.
I dont see why you get your null result but, one thing you are doing wrong is actually returning InputStream:
is= urlConn.getInputStream(); //-->(1)<--
return is;
you should read your stream in doInBackground (on worker thread), otherwise reading it in onPostExecute (UI Thread), will possibly cause NetworkOnMainThreadException, or at least ANR. Reading data from InputStream is still a network operation - data you download can be several MBs.
I have an inputStream from an HttpURLConnection. The inputStream is passed as property to an object that will later be called via its getter from the Struts2 framework to provide the stream directly to the users browser. Although the code seems to work as expected I am worried that I cannot close properly the HttpURLConnection as this will invalidate my input stream before is read from the user's browser. The code is as follows:
private void DownloadOutput(DownloadableObject retVal, URL u, String cookie) {
try {
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Cookie", cookie);
Map<String, List<String>> headers = conn.getHeaderFields();
retVal.setContentLength(conn.getContentLength());
retVal.setStream(new BufferedInputStream(conn.getInputStream()));
// in.close();
// conn.disconnect();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Is there any suggestion as what would be the optimal approach? I assume that the gc will later on clear the HttpURLConnection object but it is good to do some housekeeping pro-actively. I also assume that the "new BufferedInputStream" passed into the proxy object will be closed by the underlying struts framework(?).
convert it to string and then set it to an object
Read/convert an InputStream to a String
Streams basically represents a handle input/output source, and when you close the reference it loses the handle
http://docs.oracle.com/javase/tutorial/essential/io/streams.html
Looks like the cleaner way is to subclass the inputstream and Override the close. That way when struts will call the close, after having read the stream, you can close your connection:
private class mytest extends BufferedInputStream {
private HttpURLConnection aConn;
public mytest(HttpURLConnection conn, InputStream in) {
super(in);
this.aConn = conn;
}
public mytest(HttpURLConnection conn, InputStream in, int size) {
super(in, size);
this.aConn = conn;
}
#Override
public void close() throws IOException {
super.close();
System.out.println("The stream has been closed, time to close the connection");
aConn.disconnect();
System.out.println("Connection has been disconnected");
}
}
So the above object is the stream that will be set in the action as the inputStream parameter.
I am facing this current problem now.
I am able to send command to the device and receive response from the device from android emulator to the socket.
But, when I install the same application on tablet, there is a problem. The first time I send command to check status that device is connected or not, it send me the response that device is connected but when I send command second time it throws the following exception:
java.net.ConnectException: /192.168.1.106:8002 - Connection refused.
This is the code that does the request:
public static String sendRequestandResponse(final String host,final int port,
final String command,
final int timeoutInMillis,final int responseLength) throws UnknownHostException,NetworkSettingException
{
if (host == null)
{
throw new NullPointerException("host is null"); //NOPMD
}
Socket clientSocket=null;
try {
/**
* Creating socket connection with IP address and port number to send Command
*/
try{
clientSocket = new Socket();
SocketAddress remoteAdr = new InetSocketAddress(host, port);
clientSocket.connect(remoteAdr, 1000);
clientSocket.setSoTimeout(timeoutInMillis);
}catch (Exception e) {
e.printStackTrace();
throw new NetworkSettingException(e.getMessage());
}
final PrintWriter outPutStream = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), CHARSET));
try
{
outPutStream.print(command);
outPutStream.flush();
BufferedReader responseString = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), CHARSET));
response = new StringBuilder();
try
{
int pos = 0;
while (true)
{
pos++;
System.out.println(pos);
int i=responseString.read();
byte[] resp={(byte)i};
System.out.println(new String(resp));
response.append(new String(resp));
if(pos>=responseLength){
{
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
clientSocket.close();
Log.d("ConnectionSocket", "Socket closed with break");
break;
}
}
}
}catch (Exception e) {
e.printStackTrace();
}
finally
{
responseString.close();
}
}
finally
{
outPutStream.close();
}
}
catch(IOException ex){
}
catch(NullPointerException ex){ //NOPMD
}
finally
{
try {
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
clientSocket.close();
} catch (NullPointerException ex) { //NOPMD
} catch (IOException ex) {
}
}
return response.toString();
}
I think it doesnt close the socket first time, so second time it refuse the connection.
The same code works on emulator though.
You will get the Connection Refused only when the server is not accepting the connection.
Mostly, the Problem is the Firewall which blocks the any untrusted incoming connection.
My application shows this message mostly when the server has a firewall which block it.
So u can add the Exception list in Firewall for your application.