title: Sun Java HttpServer - Either slow in serving requests or wasting resources (TIME_WAIT/CLOSE_WAIT)
body: <p>First,</p>
  
  <p>I've searched a lot to find a solution but were not able to find an appropriate one.</p>
  
  <p><strong>Environment</strong></p>
  
  <ul>
  <li>(productive) Mongoose WebServer replies to simple GET-requests (all data are transmitted via QueryString)</li>
  <li>Apache HttpClient (single instance!) used to make hundreds of thousands single requests sequentially.</li>
  <li><p>Apache HttpClient interacting with mongoose works quite well</p>
  
  <pre><code>// after each request
  getMethod.releaseConnection();
  ...
  </code></pre></li>
  </ul>
  
  <p><strong>Problem</strong></p>
  
  <ul>
  <li>(Mock) implementation of WebServer with Sun HttpServer works fine with FireFox / Curl</li>
  <li>Using Apache HttpClient as with running against productive Server, performance is horrible (~ 1 request/second) on client</li>
  <li>Using Apache HttpClient with following code found on the net results in
  <ul>
  <li>vast performance gain on client</li>
  <li>resource waste due to as many open sockets in CLOSE_WAIT state as requests processed (until no more FDs ara available!)</li>
  </ul></li>
  </ul>
  
  <p>Code:</p>
  
  <pre><code>HttpConnectionManager mgr = httpClient.getHttpConnectionManager();
      if (mgr instanceof SimpleHttpConnectionManager) {
      ((SimpleHttpConnectionManager)mgr).shutdown();
  }
  </code></pre>
  
  <p><strong>Obviously I am mising something in the http server implementation, which causes this extreme "sloweness"</strong></p>
  
  <p>Any hint/help is appreciated.</p>
  
  <p>Thanks in advance!</p>
  
  <hr>
  
  <h2><strong>Code</strong></h2>
  
  <p><strong>HttpServer</strong>
  </p>
  
  <pre class="lang-java prettyprint-override"><code>public static void main(String[] args) throws Exception {
          //System.setProperty("sun.net.httpserver.maxIdleConnections", "10");
          //System.setProperty("sun.net.httpserver.idleInterval", "2000");
  
          HttpServer server = HttpServer.create();
  
          server.bind(new InetSocketAddress("localhost", 11111), -1);
          InetSocketAddress addr = server.getAddress();
          HttpContext contextSearch = server.createContext("/search.to",
                  new TrufflesSearchHandler());
  
          contextSearch.getFilters().add(new ParameterFilter());
          server.setExecutor(null); // creates a default executor
          server.start();
      }
  </code></pre>
  
  <p><strong>HttpHandler</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>    static class SearchHandler implements HttpHandler {
          private JSONParser jsonParser = new JSONParser();
  
          public void handle(HttpExchange exchange) throws IOException {
              Map&lt;String, Object&gt; params = (Map&lt;String, Object&gt;) exchange
                      .getAttribute("parameters");
              String expectedResponse = "";
              int expectedHitPlace = -1;
  
              try {
                  expectedResponse = (String) params.get("expectedResponse");
                  expectedHitPlace = Integer.parseInt((String) params
                          .get("expectedHitPlace"));
              } catch (Exception e) {
                  e.printStackTrace();
              }
  
              JSONArray resultArray = null;
              try {
                  resultArray = (JSONArray) jsonParser.parse(new String(Base64
                          .decodeBase64(expectedResponse)));
                  fillResponseWithDummyData(resultArray, expectedHitPlace);
              } catch (ParseException e) {
                  e.printStackTrace();
              }
              String response = "{ \"results\": " + resultArray + "}";
  
              Headers headers = exchange.getResponseHeaders();
              headers.add("Connection", "keep-alive");
              headers.add("Content-Type", "text/plain");
              headers.add("Content-length", "" + response.getBytes().length);
              // headers.add("Keep-Alive", "timeout=5 max=10");
              exchange.sendResponseHeaders(200, 0);
              // exchange.sendResponseHeaders(200, response.getBytes().length);
              OutputStream os = exchange.getResponseBody();
              os.write(response.getBytes());
              os.flush();
              os.close();
              // exchange.close();
          }
  </code></pre>
  
  <p><strong>ParameterFilter</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>@SuppressWarnings("restriction")
  public class ParameterFilter extends Filter {
  
      @Override
      public String description() {
          return "Parses the requested URI for parameters";
      }
  
      @Override
      public void doFilter(HttpExchange exchange, Chain chain)
          throws IOException {
          parseGetParameters(exchange);
          parsePostParameters(exchange);
          chain.doFilter(exchange);
      }    
  
      private void parseGetParameters(HttpExchange exchange)
          throws UnsupportedEncodingException {
  
          Map&lt;String, Object&gt; parameters = new HashMap&lt;String, Object&gt;();
          URI requestedUri = exchange.getRequestURI();
          String query = requestedUri.getRawQuery();
          parseQuery(query, parameters);
          exchange.setAttribute("parameters", parameters);
      }
  
      private void parsePostParameters(HttpExchange exchange)
          throws IOException {
  
          if ("post".equalsIgnoreCase(exchange.getRequestMethod())) {
              @SuppressWarnings("unchecked")
              Map&lt;String, Object&gt; parameters =
                  (Map&lt;String, Object&gt;)exchange.getAttribute("parameters");
              InputStreamReader isr =
                  new InputStreamReader(exchange.getRequestBody(),"utf-8");
              BufferedReader br = new BufferedReader(isr);
              String query = br.readLine();
              parseQuery(query, parameters);
          }
      }
  
       private void parseQuery(String query, Map&lt;String, Object&gt; parameters)
           throws UnsupportedEncodingException {
           String encoding = System.getProperty("file.encoding");
           if (query != null) {
               String pairs[] = query.split("[&amp;]");
  
               for (String pair : pairs) {
                   String param[] = pair.split("[=]");
  
                   String key = null;
                   String value = null;
                   if (param.length &gt; 0) {
                       key = URLDecoder.decode(param[0],
                           encoding);
                   }
  
                   if (param.length &gt; 1) {
                       value = URLDecoder.decode(param[1],
                           encoding);
                   }
  
                   if (parameters.containsKey(key)) {
                       Object obj = parameters.get(key);
                       if(obj instanceof List&lt;?&gt;) {
                           List&lt;String&gt; values = (List&lt;String&gt;)obj;
                           values.add(value);
                       } else if(obj instanceof String) {
                           List&lt;String&gt; values = new ArrayList&lt;String&gt;();
                           values.add((String)obj);
                           values.add(value);
                           parameters.put(key, values);
                       }
                   } else {
                       parameters.put(key, value);
                   }
               }
           }
      }
  
  }
  </code></pre>