2013-08-02 4 views
0

Я пытаюсь создать собственный встроенный HTTP-сервер для Java с очень конкретным использованием для внутренней закрытой системы. Использование встроенного решения, которое уже существует, означает, что мне нужно снять их, чтобы переустановить их для конкретных случаев использования моей внутренней системы.Ответ HTTP HTTP-сервера неполный

Мне удалось получить HTTP-запросы Java HTTPD от веб-браузеров, но запросы, которые получает HTTPD, являются неполными.

Ниже это сервер нить коды (делая вид на ServerSocket работает прекрасно):

public class HttpThread implements Runnable { 

    private Socket socket; 
    private DataInputStream in; 
    private PrintStream out; 
    private BufferedReader br; 
    private String EOF = "\n"; 
    private String STATUS_200 = "HTTP/1.1 200 OK" + EOF; 

    public HttpThread(Socket socket) throws IOException { 
     this.socket = socket; 
     this.in = new DataInputStream(this.socket.getInputStream()); 
     this.out = new PrintStream(new BufferedOutputStream(this.socket.getOutputStream())); 
    } 

    @Override 
    public void run() { 
     System.out.println("New thread..."); 
     try { 
      processInput(); 
      //socket.close(); 
     } catch (IOException ex) { 
      Logger.getLogger(HttpThread.class.getName()).log(Level.SEVERE, null, ex); 
     } finally { 
      if (br != null) { 
       try { 
        br.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     //System.out.println("Thread END..."); 
    } 

    private String processInput() throws IOException { 
     String line; 
     StringBuilder buff = new StringBuilder(); 
     br = new BufferedReader(new InputStreamReader(in)); 
     while ((line = br.readLine()) != null) { 
      buff.append(line); 
      System.out.println(">>> " + line); 
      if (line.trim().isEmpty()) { 
       break; 
      } 
     } 
     out.print(STATUS_200); 
     out.print("Server: Test Server\n" + 
      "Content-Type: text/html; charset=UTF-8\n" + 
      "Connection: close"); 
     out.print(EOF); 
     out.print("<html><body>yello</body></html>"); 
     out.print(EOF); 
     out.flush(); 
     System.out.println(STATUS_200); 
     return buff.toString(); 
    } 

} 

Я использую этот HTML-скрипт, чтобы проверить поток сервера для имитации запроса POST:

<html> 
<body onLoad="document.test.submit();"> 
<form action="http://localhost:9999/" method="POST" name="test"> 
    <input type=hidden name="userid" value="1443"/> 
    <input type=hidden name="password" value="1443"/> 
</form> 
</body> 
</html> 

Когда я использую браузер для вызова кодов HTML, Java HTTPD получает неполный ответ:

New thread... 
>>> POST/HTTP/1.1 
>>> Host: localhost:9999 
>>> Connection: keep-alive 
>>> Content-Length: 25 
>>> Cache-Control: max-age=0 
>>> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
>>> Origin: null 
>>> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36 
>>> Content-Type: application/x-www-form-urlencoded 
>>> Accept-Encoding: gzip,deflate,sdch 
>>> Accept-Language: en-GB,en-US;q=0.8,en;q=0.6 
>>> 
HTTP/1.1 200 OK 

New thread... 
>>> GET /favicon.ico HTTP/1.1 
>>> Host: localhost:9999 
>>> Connection: keep-alive 
>>> Accept: */* 
>>> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36 
>>> Accept-Encoding: gzip,deflate,sdch 
>>> Accept-Language: en-GB,en-US;q=0.8,en;q=0.6 
>>> 
HTTP/1.1 200 OK 

Похоже, что HTTPD получил только HTTP-заголовки и перестало получать тело POST. Могу ли я узнать о некоторых решениях для решения вышеуказанной проблемы?

Спасибо.

ответ

0

Я выключил время цикла, который делает Readline() с помощью следующего кода:

int i; 
byte[] buffer = new byte[2048]; 
i = in.read(buffer); 
for (int j = 0; j < i; j++) { 
    buff.append((char) buffer[j]); 
} 
System.out.println(buff.toString()); 

и проблема решена.

Pyranja, спасибо за помощь.

Благодаря http://kcd.sytes.net/articles/simple_web_server.php ЕСЛИ ВЫ следуете кратко. Так или иначе команда br.readline() не полностью правильно считывает строки после пустой строки.

фрагмент кода теперь должен выглядеть следующим образом:

private String processInput() throws IOException { 
     String line; 
     StringBuilder buff = new StringBuilder(); 
     int i; 
     byte[] buffer = new byte[2048]; 
     i = in.read(buffer); 
     for (int j = 0; j < i; j++) { 
      buff.append((char) buffer[j]); 
     } 
     System.out.println(buff.toString()); 
     out.print(STATUS_200); 
     out.print("Server: Test Server\n" + 
      "Content-Type: text/html; charset=UTF-8\n" + 
      "Connection: close"); 
     out.print(EOF); 
     out.print("<html><body>yello</body></html>"); 
     out.print(EOF); 
     out.flush(); 
     System.out.println(STATUS_200); 
     return buff.toString(); 
} 

Я предполагаю, что это хороший опыт обучения, как построить простой HTTP-сервер: D.

2

HTTP-заголовки и корпус разделены пустой линия (also see the HTTP RFC, особенно глава «5 запрос»). Сервер считывает гнездо Inputstream но ломает на пустой строке:

if (line.trim().isEmpty()) { 
    break; 
} 

Поэтому очевидно, что вы не получите тело. Вы должны полностью уничтожить Inputstream.

Кроме того, я бы посоветовал использовать уже существующие решения. Существует множество реализаций HTTP-сервера, которые хорошо протестированы и проверены в реальном мире. Спасите себя от головной боли и используйте существующий легкий сервер, например, Jetty, Netty или аналогичные.

+0

Эти легкие серверы легко демонтируются? Мне нужно будет их оторвать, потому что для внутреннего сервера моя среда требует много настраиваемой функции. В лучшем случае псевдо-httpserver. – thotheolh

+0

Jetty - это ServletEngine, если вы можете реализовать свои пользовательские функции в Servlet (или JAX-RS для сервисов ReSTful), это будет хороший выбор. Netty более низкий уровень, ссылаясь на [веб-страницу] (http://www.netty.io), это структура сервера/клиента.Он предлагает поддержку для написания сетевого кода для произвольных протоколов. – Pyranja

+0

Я удалил «перерыв»; и соединение с сервером просто зацикливается и ждет там, пока я не перейду в браузер, чтобы нажать кнопку «Стоп», и тело запроса, наконец, прошло. – thotheolh

Смежные вопросы