HttpUnit doesn't seem to download image files
(image/gif) by default, so I have been doing it
explicitly like this:
WebConversation session = new WebConversation();
WebResponse page;
WebResponse image;
page = session.getResponse(newsUrl);
image = session.getResponse(
SERVER_URL+'/'+page.getImages()[0].getSource());
However, after between 4000 and 5000 downloads I get
the following error. It looks like HttpUnit has used
up all the sockets on my Windows box. If I just
download html pages it works fine.
java.net.BindException: Address already in use: connect
at
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at
java.lang.reflect.Constructor.newInstance(Constructor.java:494)
at
sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1202)
at java.security.AccessController.doPrivileged(Native
Method)
at
sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1196)
at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:885)
at
java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:367)
at
com.meterware.httpunit.HttpWebResponse.readResponseHeader(HttpWebResponse.java:162)
at
com.meterware.httpunit.HttpWebResponse.readHeaders(HttpWebResponse.java:200)
at
com.meterware.httpunit.HttpWebResponse.<init>(HttpWebResponse.java:56)
at
com.meterware.httpunit.HttpWebResponse.<init>(HttpWebResponse.java:67)
at
com.meterware.httpunit.WebConversation.newResponse(WebConversation.java:76)
at
com.meterware.httpunit.WebWindow.getResource(WebWindow.java:164)
at
com.meterware.httpunit.WebWindow.getSubframeResponse(WebWindow.java:128)
at
com.meterware.httpunit.WebWindow.getResponse(WebWindow.java:121)
at
com.meterware.httpunit.WebWindow.getResponse(WebWindow.java:102)
at
com.meterware.httpunit.WebClient.getResponse(WebClient.java:87)
at slug.PageTestCase.testVolume(PageTestCase.java:107)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at
junit.framework.TestResult$1.protect(TestResult.java:106)
at
junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.net.BindException: Address already in
use: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at
java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at
java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.Socket.connect(Socket.java:507)
at java.net.Socket.connect(Socket.java:457)
at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
at
sun.net.www.http.HttpClient.openServer(HttpClient.java:365)
at
sun.net.www.http.HttpClient.openServer(HttpClient.java:477)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:214)
at sun.net.www.http.HttpClient.New(HttpClient.java:287)
at sun.net.www.http.HttpClient.New(HttpClient.java:299)
at
sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:792)
at
sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:744)
at
sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:669)
at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:913)
at
sun.net.www.protocol.http.HttpURLConnection.getHeaderFieldKey(HttpURLConnection.java:1919)
at
com.meterware.httpunit.HttpWebResponse.loadHeaders(HttpWebResponse.java:216)
at
com.meterware.httpunit.HttpWebResponse.readHeaders(HttpWebResponse.java:198)
... 24 more
Logged In: YES
user_id=1122348
I've found the cause.
WebResponse.loadResponseText() is only called when the
ContentType begins with "text" (say "text/html",
"text/javascript"). It is loadResponseText() that reads the
previously opened input stream, parses the tags, and closes
it. When lots of responses of other types are received we
build up a load of unclosed streams and run out of file
handles (I guess).
I have patched my version of WebResponse.java and
HttpWebResponse.java to use another method ignoreResponse()
for non-text responses. This simply reads the stream and
closes it.
See attached sources. This is just a hack that works around
the problem.
Workaround sources
Logged In: YES
user_id=1220573
Originator: NO
Dear Sir Runcible Spoon,
thank you for your bug report. I tried to reproduce your problem with:
http://httpunit.svn.sourceforge.net/viewvc/httpunit?view=rev&revision=935
but was not able to. With many images the tests take very long - so a first indicator of your patch working would be that the tests run much faster.
Your patch is against some code of 2006 - I'm sorry that it took so long to react and therefore we'd need to get diffs againgst the latest trunk revision to look into this. I'd appreciate your contribution for this.
I'm looking forward to your coooperation.
Yours
Wolfgang
Logged In: YES
user_id=1220573
Originator: NO
Need more information to do anything about this. What exactly
doesn't work?
Logged In: YES
user_id=1122348
Originator: YES
My, this was a long time ago.
Having looked at the available downloads. Diffing the sources, the sources I pinned up must have been for 1.6. However the problem still existed in 1.6.1 and 1.6.2, but I haven been able to work out how to build the current trunk. They look very different, so I guess it has been greatly re-worked.
If you would like to test it post a 1x1.gif on your localhost and use the following program:
import com.meterware.httpunit.*;
public class GifDownLoader
{
public static void main(String[] args) throws Exception
{
WebConversation session = new WebConversation();
int i = 1;
while(true)
{
System.out.println(i++);
WebResponse image = session.getResponse("http://localhost/1x1.gif");
}
}
}
It packs up at this point on XP:
...
3964
3965
3966
3967
Exception in thread "main" java.net.BindException: Address already in use: connect
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
...
Cheers
Logged In: YES
user_id=643287
Originator: NO
Isn't this just due to Windows by default limiting the number of sockets? Short explanation, you can not reuse a socket withing 2 minutes, and by default Windows will only allow you ot use sockets 1024-5000, so if you create more than 33 sockets per seconds you will run in to this problem.
See: http://forums.parasoft.com/index.php?showtopic=435
Logged In: YES
user_id=1122348
Originator: YES
No. The problem is that the socket used is not closed. If you change the url in my example program to download a HTML file (say http://localhost/index.html\) then httpunit will close the socket after each request and continue to download the file indefinately without problems.
My changes to 1.6 make httpunit deal file types that it does not recognise. It simply downloads the whole response from the already open socket (which it then ignores) and then it closes the socket.
Logged In: YES
user_id=37920
Originator: NO
The proposed fix breaks the use of a web response to obtain a binary stream; it appears that what we need is a pool of open webresponse objects. Once the stream is closed, we remove the item from the pool. If the pool becomes too large (settable), we close the input stream of the oldest entry.
To test this, we need a way emulate socket assignments, and I don't have an answer off the top of my head for how to do that.
Logged In: YES
user_id=643287
Originator: NO
I tried the following in WebClientTest, does that replicate the error?
public void testManyImages() throws Exception {
WebConversation wc = new WebConversation();
defineResource( "image", new byte[1024], "image/gif");
for (int i = 0; i < 10000; i++) {
WebResponse resp = wc.getResponse(getHostPath() + "/image");
// Enable line below to not get too many open files / sockets
//resp.getInputStream().close();
}
}
I'm not sure why the input stream ins not always read, perhaps in order to handle streaming (large) content. Anyway, with the change where I get the input stream and explicitly close it, then I don't get the error. Reading the code this seems clear, but since the close is not needed for text/* content, this should be fixed or documented (unless all users are supposed to read and understand the code for httpunit).
Logged In: YES
user_id=1220573
Originator: NO
Thank you for your further input.
I have added your test case proposals and tried out the results on an XP machine. I get some 3889, over 5700 and even 15000 tries as varying results.
Very strange ... The test cases are commented out for the current HttpUnitSuite until we clarify what to do.
Logged In: YES
user_id=643287
Originator: NO
One possible reason for getting varying number could be the because of the garbage collection. Since the test did not hold on to the WebResponse, it was ellageable for gc, which in turn also frees the stream. For the streams I think there is a finally clause which closes the them. So, with little memory GC runs more often, thus actually closing the streams. With much memory it does not. On my machine the default setting is actually 512MB, so I don't think any gc occurs during the test.
Logged In: YES
user_id=1312539
Originator: NO
This Tracker item was closed automatically by the system. It was
previously set to a Pending status, and the original submitter
did not respond within 14 days (the time period specified by
the administrator of this Tracker).