【问题标题】:HTTP Header with Apache HTTPComponents带有 Apache HTTPComponents 的 HTTP 标头
【发布时间】:2015-08-18 14:21:46
【问题描述】:

我用客户端聊天应用程序编写了一个基本的 http 服务器。我使用自己的 HTTP 服务器实现,因为我想了解它的功能。

客户端使用来自 Apache 的 HTTPComponents 库。

如果我向我的服务器发送 e 请求,我得到了一个失败代码:

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 标头:

                              "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;

内容长度是正文的长度,它是一个简单的 HTML 文档。在我看来,语法是正确的,但我不太确定。

这里是 Client-Worker 类:

/**
 * @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();
 }
}

所以我希望你能告诉我更多关于那些请求/响应操作的信息,并可能找到一个简单的解决方案

乔纳斯

【问题讨论】:

    标签: java httprequest httpresponse apache-httpcomponents


    【解决方案1】:

    我怀疑您忘记在 HTTP 响应标头和正文之间添加一个空的新行 (\r\n) 作为分隔符。在这种情况下,客户端将不知道它何时开始读取正文。

    您可以通过在 Apache httpclient 上启用有线日志来检查您的 HTTP 服务器返回给客户端的确切内容,方法是将此参数添加到客户端的命令行:

    -Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=DEBUG
    -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多