HTTP-сервер, поддерживающий Keep-Alive - PullRequest
2 голосов
/ 29 июня 2011

Я пытаюсь создать http-сервер на Java, способный поддерживать соединения с поддержкой активности. Я использую класс com.sun.net.httpserver.HttpServer.

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class httpHandler implements HttpHandler {

private String resp = "<?xml version='1.0'?><root-node></root-node>";

private OutputStream os = null;

public void handle(HttpExchange t) throws IOException {
    System.out.println("Handling message...");
    java.io.InputStream is = t.getRequestBody();

    System.out.println("Got request body. Reading request body...");
    byte[] b = new byte[500];
    is.read(b);
    System.out.println("This is the request: " + new String(b));

    String response = resp;
    Headers header = t.getResponseHeaders();
    header.add("Connection", "Keep-Alive");
    header.add("Keep-Alive", "timeout=14 max=100");
    header.add("Content-Type", "application/soap+xml");
    t.sendResponseHeaders(200, response.length());

    if(os == null) {
        os = t.getResponseBody();
    }

    os.write(response.getBytes());

    System.out.println("Done with exchange. Closing connection");
    os.close();
}

public static void main(String[] args) {
    HttpServer server = null;
    try {
        server = HttpServer.create(new InetSocketAddress(8080), 5);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    server.createContext("/", new httpHandler());
    server.setExecutor(null); // creates a default executor
    System.out.println("Starting server...");
    server.start();
}
}

Клиент не закрывает соединение. Похоже, что сервер закрывает его сразу после обмена. Я попытался удалить строку os.close, но тогда сервер не будет отвечать на второй запрос. Но это тоже не закрывает. У меня есть ощущение, что это связано с выполнением чего-либо в основном коде с помощью объекта server, но я понятия не имею, что. Google тоже мало что показывает.

У кого-нибудь есть идеи? Любая помощь приветствуется.

Ответы [ 4 ]

3 голосов
/ 29 июня 2011

Похоже, проблема в том, что вы не удалили все данные из запроса.Вы должны продолжать делать is.read() до тех пор, пока он не вернет -1, затем закройте его.

Поскольку вы не исчерпали запрос, остаются еще байты.Сервер не может просто «перейти» к следующему запросу;это не как диск, а как лента.Сервер должен прочитать (и отбросить) все данные из текущего запроса, прежде чем он сможет достичь следующего запроса.

Без ограничения это можно использовать для атаки на сервер;таким образом, сервер будет пытаться использовать только предел, который по умолчанию составляет 64 КБ.Вы, вероятно, получаете запрос размером более 64K.

Обычно обработчик должен сначала прочитать весь запрос.Иначе как он знает, как обслуживать запрос?

Если серьезно, то если запрос не будет обработан первым, может возникнуть тупик.Клиенты обычно просты: они пишут запрос, а затем читают ответ.Если сервер записывает ответ до того, как прочитает весь запрос, клиент все еще может писать запрос.Оба пишут друг другу, но ни один не читает.Если буферы заполнены, то мы зашли в тупик, оба блокируются при записи.Обратите внимание, что для write () нет времени ожидания!

1 голос
/ 20 июля 2012

Почему вы получаете ResponseBody OutputStream, только если предыдущий был нулевым?

if(os == null) {
    os = t.getResponseBody();
}

Может быть лучше каждый раз получать OutputStream, так как вы не можете быть уверены, что предыдущий идентичен одному изтекущий запрос.

1 голос
/ 21 сентября 2011

попробуйте позвонить t.close(), сервер ответит

0 голосов
/ 29 июня 2011

Это клиент , который отправляет заголовки поддержки активности. Если это так, HttpServer не закрывает соединение. Вам не нужно ничего с этим делать.

...