I am writing a Java program to compute the http connection time for (lets say) 5 http connection (to different IP).
The first scenario is, without threading, the program connect and testing the http server one by one which mean when finish one server testing then proceed to another. In this scenario, the time taken is very long. Moreover, the timeout is not working properly, for example, I have set the
setConnectTimeout(5 * 1000);
setReadTimeout(5 * 1000);
but the time return by
long starTime = System.currentTimeMillis();
c.connect();
String line;
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while ((line = in.readLine()) != null){
page.append(line);
elapseTime = System.currentTimeMillis() - starTime;
can be more than 5 second, some even go up to 30 second (but I set 5 second as timeout only).
So, I make the implementation to be multithreading. But the result is more rediculous. I can't even get one successful connection now.
Now my question is, can we establish multiple connection by using multiple thread? If answer is yes, what I have to notice to avoid the issue above?
Thank.
*Extra info*
1) I am computing the proxy connection speed, so, ya, the connection is proxy connection.
2) The threads that I created is around 100. I think it should be fine right?
How are you setting up your connections? Are you using a socket connection? If so, depending on how you setup your socket, you may find that the connection timeout value may be ignored
Socket sock = new Socket("hostname", port);
sock.setSoTimeout(5000);
sock.connect();
Will actually not set the connect timeout value, as the constructor will already attempt to connect.
SocketAddress sockaddr = new InetSocketAddress(host, port);
Socket sock = new Socket();
sock.connect(sockaddr, 5000);
Will more accurately connect with a timeout value. This may explain why your socket timeouts are not working.
public float getConnectionTime(){
long elapseTime = 0;
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAdd, portNum));
URL url;
StringBuilder page = new StringBuilder();
HttpURLConnection uc = null;
try {
uc = (HttpURLConnection)Main.targetMachine.openConnection(proxy);
// uc = (HttpURLConnection)Main.targetMachine.openConnection();
uc.setConnectTimeout(Main.timeOut);
uc.setReadTimeout(Main.timeOut);
long starTime = System.currentTimeMillis();
uc.connect();
// if (uc.getResponseCode() == HttpURLConnection.HTTP_OK){
// System.out.println("55555");
// }else System.out.println("88888");
String line;
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while ((line = in.readLine()) != null){
page.append(line);
elapseTime = System.currentTimeMillis() - starTime;
}
} catch (SocketTimeoutException e) {
System.out.println("time out lo");
// e.printStackTrace();
return 9999; //if time out, use 9999 signal.
} catch (IOException e){
System.out.println("open connection error, connect error or inputstream error");
// e.printStackTrace();
return 9999;
}finally{
if (uc != null)
uc.disconnect();
}
// System.out.println(page);
return (float)elapseTime / 1000;
}
Related
I have an interesting scenario here. I have a proxy server address that is supposed to provide me a new exit IP every time I make an HTTP request to it. I have noticed that the exit IP will change only after I restart the program, as opposed to every loop iteration. Below is my source.
Loop calls getHTML every iteration:
String result = getHTML("https://wtfismyip.com/text");
public static String getHTML(String urlToRead) throws Exception {
InetSocketAddress addy = new InetSocketAddress("example.proxy.com", 1234);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addy);
StringBuilder result = new StringBuilder();
URL url = new URL(urlToRead);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
conn.setRequestMethod("GET");
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
rd.close();
conn.disconnect();
return result.toString();
}
Result will continue to be the same IP every time, until I restart the program. I feel like some stream or socket hasn't been closed yet and it keeps the connection alive.
Found the answer to my problem. The TCP socket was being kept alive, and would allow it to keep tunneling to the proxy without reconnecting.
I needed to add this statement somewhere in my code, I put it at the beginning of this class's initialization.
System.setProperty("http.keepAlive", "false");
I try to connect with my server by using socket on android. I want it to work like this; when i send a request to the server, if there is a response, call my response function. If the timeout of 500 ms happens (will check the exception and the boolean i set), i want to execute another function. But with this code im using, when i send something to the server and wait for response, it executes the onServerResponse function if there is a response and doesnt do anything(hangs) when there is not a response. How can i edit this code so it will throw a timeout exception when there is no response?
boolean control = false;
try{
Socket socket = new Socket();
socket.setSoTimeout(500);
socket.connect(new InetSocketAddress(InetAddress.getByName(SERVER_IP),SERVER_PORT));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
bw.write("asdasd\n");
bw.flush();
control = true;
int readInt = -1;
String read = null;
StringBuilder sb = new StringBuilder("");
while((readInt = socket.getInputStream().read()) != -1){
sb.append((char)readInt);
}
read = sb.toString();
if(read != null && read.trim().length() > 0){ onServerResponse(read); }
}catch(Exception e){ Log.v("Main", "GOT AN ERROR: "+e+control); }
Problem solved, see the comments for answer.
I'm not sure if this answers your question, but setSoTimeout only applies to reads on the socket after it is connected, not to establishing the connection itself. For that, use the socket.connect(SocketAddress address, int timout) overload.) overload. You probably want to use both.
Something like this would work:
Socket socket = new Socket();
InetAddress addr = InetAddress.getByName(SERVER_IP);
SocketAddress sockaddr = new InetSocketAddress(addr, SERVER_PORT);
// 500ms is too short, up to you.
// normal time would be 5 to 20 seconds, depends on network (intranet/internet)
socket.connect(sockaddr, 500);
// 500ms to timeout reading from the socket
socket.setSoTimeout(500);
How should one deal with clients disconnecting unexpectedly. I want to keep the server running/listening unless explicitly stated to close by the client.
For example, my server is listening and then the client is closed which causes the server's method to end - how can I get it to return to the beginning of the method as it were?
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BasicProtocol bp = new BasicProtocol(password);
out.println(bp.processInput(""));
String inputLine;
while((inputLine = in.readLine()) != null ){
System.out.println("Client asks: " + inputLine);
out.println(bp.processInput(inputLine));
}
As above, if a connection reset error occurs how can it wait to be reconnected to?
For instance you can have a while loop at the method with a boolean variable that is changed when the client wants to close. As such:
boolean isRunning = true;
while (isRunning) {
//Your current method - when client wants to disconnect just set isRunning = false;
}
Some times work throuw the proxy server and reading prom buffer content my program to think so more time... until i close them. How set program code that from some seconds if do not have any answer from server to take another server?
URL url = new URL(linkCar);
String your_proxy_host = new String(proxys.getValueAt(xProxy, 1).toString());
int your_proxy_port = Integer.parseInt(proxys.getValueAt(xProxy, 2).toString());
Proxy proxy = null;
// System.out.println(proxys.getValueAt(xProxy, 3).toString());
// if (proxys.getValueAt(xProxy, 3).toString().indexOf("HTTP") > 0)
// {
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(your_proxy_host, your_proxy_port));
// } else {
// proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(your_proxy_host, your_proxy_port));
// }
HttpURLConnection connection = (HttpURLConnection)url.openConnection(proxy);
connection.setConnectTimeout(1000);
connection.connect();
String line = null;
StringBuffer buffer_page = new StringBuffer();
BufferedReader buffer_input = new BufferedReader(new InputStreamReader(connection.getInputStream(),"cp1251"));
int cc = 0;
//this is thinking place!!!
while ((line = buffer_input.readLine()) != null && cc < 7000) {
buffer_page.append(line);
cc++;
}
doc = Jsoup.parse(String.valueOf(buffer_page));
connection.disconnect();
i tried to use counter but it not work... What exception i can use to catch this situation by my control?
You need to use URLConnection.setReadTimeout. From the specification,
Sets the read timeout to a specified timeout, in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. If the timeout expires before there is data available for read, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout.
As you can see, reads that time-out will throw SocketTimeoutException, which you can catch appropriately, e.g.
try (BufferedReader buffer_input = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "cp1251"))) {
String line;
while ((line = buffer_input.readLine()) != null) {
buffer_page.append(line);
}
} catch (SocketTimeoutException ex) {
/* handle time-out */
}
Note that you need to be careful when using readLine as above -- this will strip all \r and \n from the input.
I'm connecting to a simple RSS feed using HTTPUrlConnection. It works perfectly. I'd like to add a timeout to the connection since I don't want my app hanging in the event of a bad connection or whatever. This is the code I use and the setConnectTimeout method doesn't have any effect whatsoever.
HttpURLConnection http = (HttpURLConnection) mURL.openConnection();
http.setConnectTimeout(15000); //timeout after 15 seconds
...
If it helps I'm developing on android.
You should try to set the read timeout as well (http.setReadTimeout()). Oftentimes, a web server will happily accept your connection, but it might be slow in actually responding to the request.
You probably either/both:
1) Don't read anything from connection
2) Don't catch & handle the exception properly
As mentioned here, use logic similar to this:
int TIMEOUT_VALUE = 1000;
try {
URL testUrl = new URL("http://google.com");
StringBuilder answer = new StringBuilder(100000);
long start = System.nanoTime();
URLConnection testConnection = testUrl.openConnection();
testConnection.setConnectTimeout(TIMEOUT_VALUE);
testConnection.setReadTimeout(TIMEOUT_VALUE);
BufferedReader in = new BufferedReader(new InputStreamReader(testConnection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
answer.append(inputLine);
answer.append("\n");
}
in.close();
long elapsed = System.nanoTime() - start;
System.out.println("Elapsed (ms): " + elapsed / 1000000);
System.out.println("Answer:");
System.out.println(answer);
} catch (SocketTimeoutException e) {
System.out.println("More than " + TIMEOUT_VALUE + " elapsed.");
}
I had a similar problem - because the HttpUrlConnection won't time out mid-download. For example, if you turn off wifi when download is going, mine continued to say it is downloading, stuck at the same percentage.
I found a solution, using a TimerTask, connected to a AsyncTask named DownloaderTask. Try:
class Timeout extends TimerTask {
private DownloaderTask _task;
public Timeout(DownloaderTask task) {
_task = task;
}
#Override
public void run() {
Log.w(TAG,"Timed out while downloading.");
_task.cancel(false);
}
};
Then in the actual download loop set a timer for timeout-error:
_outFile.createNewFile();
FileOutputStream file = new FileOutputStream(_outFile);
out = new BufferedOutputStream(file);
byte[] data = new byte[1024];
int count;
_timer = new Timer();
// Read in chunks, much more efficient than byte by byte, lower cpu usage.
while((count = in.read(data, 0, 1024)) != -1 && !isCancelled()) {
out.write(data,0,count);
downloaded+=count;
publishProgress((int) ((downloaded/ (float)contentLength)*100));
_timer.cancel();
_timer = new Timer();
_timer.schedule(new Timeout(this), 1000*20);
}
_timer.cancel();
out.flush();
If it times out, and won't download even 1K in 20 seconds, it cancels instead of appearing to be forever downloading.
I was facing the same issue. Setting the connectionTimeout and readTimeout does not seems to return the exception as expected, but take really. It took me while to check the URLConnection() Method and understand what is going on. In the documentation for setConnectTimeout there is a warning
"if the hostname resolves to multiple IP addresses, this client will try each. If connecting to each of these addresses fails, multiple timeouts will elapse before the connect attempt throws an exception."
This mean s if you have 10 ips resolved by your host your actual time out will "10*readTimeoutSet".
You can check ips for the the host name here
http.setConnectTimeout(15000);
http.setReadTimeout(15000);
It's caused by:
1. You are connected to wifi but you dont have internet connection.
2. You are connected to GSM data but your transfer is very poor.
In both cases you get a host exception after about 20seconds. In my opinion the best way to get correct is:
public boolean isOnline() {
final int TIMEOUT_MILLS = 3000;
final boolean[] online = {false};
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
final long time = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(TIMEOUT_MILLS);
urlc.setReadTimeout(TIMEOUT_MILLS);
urlc.connect();
if (urlc.getResponseCode() == 200) {
online[0] = true;
}
} catch (IOException e) {
loger.add(Loger.ERROR, e.toString());
}
}
}).start();
while (((System.currentTimeMillis() - time) <= TIMEOUT_MILLS)) {
if ((System.currentTimeMillis() - time) >= TIMEOUT_MILLS) {
return online[0];
}
}
}
return online[0];
}
remember - use it in asynctask or service.
Its simple solution, you are starting new Thread with HttpUrlConnection (remember use start() not run()). Than in while loop you are waiting 3 sec for result. If nothing happend return false. This way let you avoid waiting for host exception and avoid problem with not working setConnectTimeout() when you dont have internet connection.
A zero value means infinit time out, which means connection must occure and normally zero is default:
connection.setConnectTimeout(0);
connection.setReadTimeout(0);
refer to here
Try to set the ConnectionTimeout before openning the connection.