2016-03-21 11 views
2

Ich verwende einen einfachen Http-Server von com.sun.net.httpserver, wie in simple HTTP server in Java using only Java SE API beschrieben.Stop HttpServer nach Anfrage werden

Alles funktioniert gut, aber ich bin mir nicht sicher, wie ich den Server sauber herunterfahren kann, sobald ich ihn nicht mehr brauche. Ich möchte den Server nicht stoppen, während er noch die Daten für eine Anfrage sendet, nur wenn er sich im Leerlauf befindet.

Mein spezielles Szenario ist eine Desktop-Anwendung, die OAuth Tanz durchführt. Ich verwende einen lokalen Webserver, der in der Anwendung eingebettet ist, um eine Rückrufantwort bereitzustellen. Die Anwendung startet einen Desktopbrowser, um die Serverantwort mithilfe der API java.awt.Desktop.browse anzuzeigen.

Ich habe versucht, HttpServer.stop(0) direkt aus meiner HttpHandler.handle Funktion aufrufen, nachdem ich die Antwort-Seite in die HttpExchange Antwortausgabestrom geschrieben haben, aber das ist zu früh, der Browser zeigt ERR_EMPTY_RESPONSE.

Das gleiche geschieht, wenn ich den Server stoppe, sobald meine Hauptanwendung ihre Arbeit beendet hat - das ist oft zu früh, die HttpServer hat das Senden der Daten in diesem Moment noch nicht abgeschlossen.

Ich könnte ein paar Sekunden Verzögerung Wert zu stoppen, aber ich möchte eine ordnungsgemäße und saubere Synchronisation erreichen.

Was ist eine geeignete Lösung?

+0

können Sie einfach eine Anfrage an den Server senden - Befehl shutdown, nachdem der Kunde alle Daten akzeptiert? –

+0

@SashaSalauyou Das hört sich interessant an. Allerdings ist der Client in diesem Fall ein Desktop-Webbrowser, und ich habe keine Kontrolle darüber, abgesehen von der Webseite, die ich ihm diene. Vielleicht könnte es eine Möglichkeit geben, einige Daten von der Seite mit Hilfe von Javascript zu senden, aber selbst wenn dies der Fall ist, was ist, wenn das Javascript auf dem server.server deaktiviert/nicht unterstützt wird, vielleicht mit Javascri – Suma

Antwort

1

kann ich eine Lösung anbieten, basierend auf einem CountDownLatch + individuelle ExecutorService, die als Testamentsvollstrecker up für HttpServer gesetzt:

public void runServer() throws Exception { 
    final ExecutorService ex = Executors.newSingleThreadExecutor(); 
    final CountDownLatch c = new CountDownLatch(1); 

    HttpServer server = HttpServer.create(new InetSocketAddress(8888), 0); 

    server.createContext("/test", (HttpExchange h) -> { 
     StringBuilder resp = new StringBuilder(); 
     for (int i = 0; i < 1_000_000; i++) 
      resp.append(i).append(", "); 
     String response = resp.toString(); 
     h.sendResponseHeaders(200, response.length()); 
     OutputStream os = h.getResponseBody(); 
     os.write(response.getBytes()); 
     os.close(); 
     c.countDown();   // count down, letting `c.await()` to return 
    }); 

    server.setExecutor(ex);  // set up a custom executor for the server 
    server.start();    // start the server 
    System.out.println("HTTP server started"); 
    c.await();     // wait until `c.countDown()` is invoked 
    ex.shutdown();    // send shutdown command to executor 
    // wait until all tasks complete (i. e. all responses are sent) 
    ex.awaitTermination(1, TimeUnit.HOURS); 
    server.stop(0); 
    System.out.println("HTTP server stopped"); 
} 

I-Test in dieser Umgebung auf unsere Arbeit Netzwerk haben, und es scheint, richtig zu arbeiten. HttpServer stoppt nicht früher als Antwort vollständig gesendet wird, also denke ich, das ist genau das, was Sie brauchen.

Ein anderer Ansatz beendet möglicherweise nicht den Executor ex, aber sendet dort eine neue Task, die server.stop() enthält, nachdem die Antwort in einen Stream geschrieben wurde. Da ex single-threaded erstellt wird, wird eine solche Task nicht früher ausgeführt als die vorherige Task, d. e. vollständig gesendet wird eine Antwort:

public void run() throws Exception { 
    final ExecutorService ex = Executors.newSingleThreadExecutor(); 
    final HttpServer server = HttpServer.create(new InetSocketAddress(8888), 0); 

    server.createContext("/test", (HttpExchange h) -> { 
     // ... generate and write a response 
     ex.submit(() -> { 
      server.stop(0); 
      System.out.println("HTTP server stopped"); 
     }); 
    }); 
    server.setExecutor(ex); 
    server.start(); 
    System.out.println("HTTP server started"); 
} 

Weitere Informationen finden Sie ExecutorService

Verwandte Themen