2015-08-18 3 views
0

Я пишу базовый http-сервер с клиентским приложением чата. Я использую собственную реализацию HTTP-сервера, потому что хочу понять функциональность.Заголовок HTTP с Apache HTTPComponents

Клиент использует библиотеку HTTPComponents из Apache.

Если я отправить электронный запрос на мой сервер, я получил Неудачу с этим Кодом ошибки:

org.apache.http.ProtocolException: Invalid header: <html> 
at org.apache.http.impl.io.AbstractMessageParser.parseHeaders(AbstractMessageParser.java:232) 
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:268) 
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165) 
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272) 
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124) 
at com.ssjd.client.sockets.SSJDClient.getNachrichten(SSJDClient.java:130) 
at com.ssjd.client.sockets.SSJDClient.run(SSJDClient.java:82) 
at java.lang.Thread.run(Thread.java:745) 

Я отсылал заголовок вручную с помощью этого содержащего текст:

       "HTTP/1.1 200 OK\n " 
           + "Via: HTTP/1.1 localhost\n " 
           + "Server: Apache/1.3\n " +       
          "Content-type:  text/plain; 

           charset=UTF-8\n " + "content-length:" 
           + body.getBytes().length; 

Содержания Длины ist длина основного текста, который является простым документом HTML. В моем oppinion, синтаксис правильно, но im не совсем уверен.

Здесь класс Клиент-работник:

/** 
* @throws IOException 
* @throws UnknownHostException 
* 
*/ 
public SSJDClient() throws UnknownHostException, IOException 
{ 
    socket = new Socket("localhost", PORT_SERVER); 
} 

@Override 
public void run() 
{ 
    try 
    { 
    getNachrichten(); 
    } 
    catch (IOException | HttpException e) 
    { 
    LOGGER.log(Level.INFO, "Fehler beim Verarbeiten der Serverantwort", e); 
    } 

} 

/** 
    * @throws IOException 
    * @throws HttpException 
    * 
    */ 
    protected void getNachrichten() throws IOException, HttpException 
    { 
    HttpProcessor httpproc = HttpProcessorBuilder.create().add(new RequestContent()) 
    .add(new RequestTargetHost()).add(new RequestConnControl()) 
    .add(new RequestUserAgent("Mozilla/39")).add(new RequestExpectContinue()).build(); 

HttpRequestExecutor httpexecutor = new HttpRequestExecutor(
    HttpRequestExecutor.DEFAULT_WAIT_FOR_CONTINUE); 

HttpCoreContext coreContext = HttpCoreContext.create(); 
HttpHost host = new HttpHost("localhost", RequiredNetworkInformationInterface.PORT_SERVER); 
coreContext.setTargetHost(host); 

DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024); 
ConnectionReuseStrategy connStrategy = DefaultConnectionReuseStrategy.INSTANCE; 

try 
{ 
    // Hier ist die eigentliche Anfrage die zum Server geschickt wird. 
    HttpEntity requestBodie = new StringEntity("This is the first test request", 
     ContentType.create("text/plain", Consts.UTF_8)); 

    if (!conn.isOpen()) 
    { 
    Socket httpSocket = new Socket(host.getHostName(), host.getPort()); 
    conn.bind(httpSocket); 
    } 
    BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", ""); 
    //wird auf die Anfrage gesetzt 
    request.setEntity(requestBodie); 
    LOGGER.log(Level.INFO, ">> Request URI: " + request.getRequestLine().getUri()); 

    httpexecutor.preProcess(request, httpproc, coreContext); 
    //Anfrage wird abgeschickt und es wird auf Antwort gewartet 
    HttpResponse response = httpexecutor.execute(request, conn, coreContext); 
    httpexecutor.postProcess(response, httpproc, coreContext); 

    LOGGER.log(Level.INFO, "<< Anfragestatus: " + response.getStatusLine()); 
    LOGGER.log(
     Level.INFO, 
     "Body der Anfrage: " 
      + (EntityUtils.toString(response.getEntity()) != "" ? "Leer" : EntityUtils 
       .toString(response.getEntity()))); 

    cache.add(getStringFromInputStream(response.getEntity().getContent())); 

    // umkopieren auf ein Array, damit das wieder angezeigt werden kann 
    String[] strings = new String[cache.size()]; 

    for (int j = 0; j < cache.size(); j++) 
    { 
    strings[ j ] = cache.get(j); 
    } 

    // in die Liste fügen 
    getView().getVerlaufsPanel().getVerlaufListe().setListData((strings) ); 
    getView().getVerlaufsPanel().repaint(); 

    if (!connStrategy.keepAlive(response, coreContext)) 
    { 
    conn.close(); 
    } 
    else 
    { 
    LOGGER.log(Level.INFO, "Connection ist geschlossen"); 
    } 

} 
catch (Exception e) 
{ 
    LOGGER.log(Level.SEVERE, "Fehler beim Senden der Anfrage", e); 
} 
finally 
{ 
    conn.close(); 
} 
} 

// convert InputStream to String 
private String getStringFromInputStream(InputStream is) 
{ 

StringBuilder sb = new StringBuilder(); 

String line; 
try (BufferedReader br = new BufferedReader(new InputStreamReader(is ) )) 
{ 

    while ((line = br.readLine()) != null) 
    { 
    sb.append(line); 
    } 

} 
catch (IOException e) 
{ 
    e.printStackTrace(); 
} 

return sb.toString(); 

} 

@Override 
public void actionPerformed(ActionEvent e) 
{ 
    switch (e.getID()) 
    { 
    case COMMAND_SENDEN: 
     LOGGER.log(Level.INFO, "Nachricht wird zum Server gesendet"); 
     this.run(); 
     break; 
    } 
    } 

@Override 
protected MainFrame createView() 
{ 
    return new MainFrame(); 
} 
} 

Так что я надеюсь, что вы можете сказать мне больше о тех Request/Операции реагирования и могут нашли простое решение

Джонас

ответ

0

Я подозреваю, что вы забыли добавить пустую новую строку (\ r \ n) для разделителя между заголовками HTTP-ответа и телом. В этом случае клиент не узнает, когда он начал читать тело.

Вы можете проверить, что именно ваш HTTP сервер возвращает клиенту, позволяя журналы проволочных на Apache HTTPClient, добавив эти параметры в командной строке вашего клиента:

-Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=DEBUG 
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog 
Смежные вопросы