-1

我試圖做的事:從HttpClient的Httpcomponents的HttpCore和HttpClient的HTTP_STATUS 400

  1. 發送請求(基於HttpComponents的HttpClient 4.5)。
  2. 在HttpServer中接收該請求(基於HttpComponents HttpCore 4.4.1)。
  3. HttpServer必須以不同的HttpStatus代碼和字符串實體作爲主體回答HttpClient。

問題:如果HttpServer使用狀態碼200(或任何其他,未檢查)作出回答,那麼它工作正常,服務器端沒有例外。但是如果服務器設置了答案狀態碼400,那麼在HttpServer上發生IOException異常。俄語說明是「Удаленныйхостпринудительноразорвалсуществующееподключение」,在英語中我認爲它是「客戶端關閉連接」。簡單的一點:在狀態200上沒有問題,在400上它是服務器上發生的異常。

異常字符串:

java.io.IOException的:Удаленныйхостпринудительноразорвалсуществующееподключение 在sun.nio.ch.SocketDispatcher.read0(本機方法)〜[NA:1.7.0_51] 在sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)〜[na:1.7.0_51] at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)〜[na:1.7.0_51] (sun.nio.ch.IOUtil.read(IOUtil.java:197)〜[na:1.7.0_51] at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:379)〜[na:1.7。 0_51] at org.apache.http.nio.reactor.ssl.SSLIOSession.receiveEncryptedData(SSLIOSession.java:449)〜[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.nio。 reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:503)〜[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch。 java:122)〜[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:164)[httpcore-nio-4.4 .jar:4.4.1] at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:339)[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:317)[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor .AbstractIOReact or.execute(AbstractIOReactor.java:278)[httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)[ httpcore-nio-4.4.1.jar:4.4.1] at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor $ Worker.run(AbstractMultiworkerIOReactor.java:590)[httpcore-nio-4.4.1.jar :4.4.1] 在java.lang.Thread.run(Thread.java:744)[NA:1.7.0_51]

的HttpServer代碼:

HttpProcessor httpproc = HttpProcessorBuilder.create() 
    .add(new ResponseDate()) 
    .add(new ResponseServer("HTTP/1.1 WTX Server")) 
    .add(new ResponseContent()) 
    .add(new ResponseConnControl()).build(); 
UriHttpAsyncRequestHandlerMapper reqistry = new UriHttpAsyncRequestHandlerMapper(); 
reqistry.register("*", new HttpServerURLHandler()); 
HttpAsyncService protocolHandler = new HttpServerConnectionsHandler(httpproc, reqistry); 
try { 
     String keyStoreFile = Config.getString("HTTPServer.keyStoreFile"); 
     String keyStoreFilePassword = Config.getString("HTTPServer.keyStoreFilePassword"); 
     FileInputStream fin = new FileInputStream(keyStoreFile); 
     KeyStore keystore = KeyStore.getInstance("jks"); 
     keystore.load(fin, keyStoreFilePassword.toCharArray()); 
     KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     kmfactory.init(keystore, keyStoreFilePassword.toCharArray()); 
     KeyManager[] keymanagers = kmfactory.getKeyManagers(); 
     SSLContext sslcontext = SSLContext.getInstance("TLS"); 
     sslcontext.init(keymanagers, null, null); 
     NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory = new SSLNHttpServerConnectionFactory(sslcontext, null, ConnectionConfig.DEFAULT); 

     IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory); 

     IOReactorConfig config = IOReactorConfig.custom() 
       //.setIoThreadCount(10) 
       //.setSoTimeout(5000) 
       //.setConnectTimeout(4000) 
       //.setSoKeepAlive(true) 
       //.setSoReuseAddress(true) 
       //.setRcvBufSize(65535) 
       //.setTcpNoDelay(true) 
       .build(); 

     ListeningIOReactor ioReactor = new DefaultListeningIOReactor(config); 
     ioReactor.listen(new InetSocketAddress(socketAddr, socketPort)); 
     ioReactor.execute(ioEventDispatch); 

    } catch (Exception e) { 
     MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPSERVER.toString()); 
     logger.error("Error while creating HTTP Server instance.", e); 
    } 

URL投手代碼:

public class HttpServerURLHandler implements HttpAsyncRequestHandler<HttpRequest> { 

public static final Logger logger = LoggerFactory.getLogger(HttpServerURLHandler.class); 

private BasicHttpResponse httpResponse = null; 

public HttpServerURLHandler() { 
    super(); 
} 

public HttpAsyncRequestConsumer<HttpRequest> processRequest(final HttpRequest request, final HttpContext context) { 
    return new BasicAsyncRequestConsumer(); 
} 

public void handle(final HttpRequest httpRequest, final HttpAsyncExchange httpExchange, final HttpContext httpContext) throws HttpException, IOException { 
    String string1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ++++++++++++++++++++++++++++++++++++++++++++++++abcdefghijklmnopqrstuvwxyz"; 
    string1 +=  "ABCDEFGHIJKLMNOPQRSTUVWXYZ++++++++++++++++++++++++++++++++++++++++++++++++abcdefghijklmnopqrstuvwxyz"; 

    int httpCode = 400; 

    String httpCodeString = EnglishReasonPhraseCatalog.INSTANCE.getReason(httpCode, Locale.ENGLISH); 
    BasicHttpResponse httpResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, httpCode, httpCodeString); 
    NStringEntity answerEntity = new NStringEntity(stringXML, Consts.UTF_8); 
    httpResponse.setEntity(answerEntity); 
    httpExchange.submitResponse(new BasicAsyncResponseProducer(httpResponse)); 
} 

}

客戶端代碼:

RequestConfig config = RequestConfig.custom() 
      .setConnectTimeout(20000) 
      .setConnectionRequestTimeout(20000) 
      .setSocketTimeout(20000) 
      .build(); 

    SSLContext sslContext = null; 
    try { 
     TrustStrategy trustStrategy = new TrustStrategy() { 
      public boolean isTrusted(X509Certificate[] arg0, String arg1) { 
       return true; 
      } 
     }; 
     sslContext = new SSLContextBuilder().loadTrustMaterial(null, trustStrategy).build(); 
    } catch (Exception e) { 
     MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString()); 
     logger.error("Error while creating SSL context for making HTTP request", e); 
    } 

    CloseableHttpClient client = HttpClientBuilder.create() 
      .setDefaultRequestConfig(config) 
      .setSSLContext(sslContext) 
      .setSSLHostnameVerifier(new NoopHostnameVerifier()) 
      .build(); 

    String stringURL = "https://serverhost:port/"; 
    try { 
     HttpPost post = new HttpPost(stringURL); 
     post.setEntity(httpClientRequest.getEntity()); 
     CloseableHttpResponse httpResponse = client.execute(post); 

     // Consume entity code 
     HttpEntity responseEntity = httpResponse.getEntity(); 
     String stringXMLAnswer = EntityUtils.toString(responseEntity); 
     EntityUtils.consume(responseEntity); 

     // Some next operations with responseEntity 

    } catch (Exception e) { 
     MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString()); 
     logger.error("Error while make request.", e); 
    } finally { 
     try { 
      // Closing connection 
      client.close(); 
     } catch (Exception e) { 
      MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString()); 
      logger.error("Error while closing connection after making request", e); 
     } 
    } 
+0

您是否在使用非2xx狀態的情況下使用郵件內容? – oleg

+0

不,這種情況只有在服務器設置回答狀態代碼400時纔會發生。我用200,401,402代碼進行了測試,結果正常。問題僅在400錯誤代碼中。我必須添加一些信息:400代碼的問題只存在於非空實體中。如果服務器沒有設置實體或設置空實體,那麼它工作正常。 – lanmaster

+0

您是否使用了響應消息的內容? – oleg

回答

0

我發現org.apache.http.protocol。ResponseConnControl代碼

 if (status == HttpStatus.SC_BAD_REQUEST || 
      status == HttpStatus.SC_REQUEST_TIMEOUT || 
      status == HttpStatus.SC_LENGTH_REQUIRED || 
      status == HttpStatus.SC_REQUEST_TOO_LONG || 
      status == HttpStatus.SC_REQUEST_URI_TOO_LONG || 
      status == HttpStatus.SC_SERVICE_UNAVAILABLE || 
      status == HttpStatus.SC_NOT_IMPLEMENTED) { 
     response.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE); 
     return; 
    } 

我的問題由此狀態碼複製。

相關問題