Java Httpcomponents httpcore和httpclient HTTP_状态400

Java Httpcomponents httpcore和httpclient HTTP_状态400,java,apache-httpclient-4.x,apache-httpcomponents,http-status-code-400,http-status-code-200,Java,Apache Httpclient 4.x,Apache Httpcomponents,Http Status Code 400,Http Status Code 200,我正在努力做到: 从HttpClient发送请求(基于HttpComponents HttpClient 4.5) 在HttpServer中接收该请求(基于HttpComponents HttpCore 4.4.1) HttpServer必须以不同的HttpStatus代码和字符串实体作为主体响应HttpClient 问题:若HttpServer使用状态代码200(或任何其他状态代码,未选中)进行应答,那个么它工作正常,服务器端并没有异常。但若服务器设置了应答状态代码400,那个么HttpSer

我正在努力做到:

  • 从HttpClient发送请求(基于HttpComponents HttpClient 4.5)
  • 在HttpServer中接收该请求(基于HttpComponents HttpCore 4.4.1)
  • HttpServer必须以不同的HttpStatus代码和字符串实体作为主体响应HttpClient
  • 问题:若HttpServer使用状态代码200(或任何其他状态代码,未选中)进行应答,那个么它工作正常,服务器端并没有异常。但若服务器设置了应答状态代码400,那个么HttpServer上就发生了IOException。俄语的描述是“Уааааааааааааааааааааааааааа107。简单的一个:在状态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.051] 在sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)~[na:1.7.051] 在sun.nio.ch.IOUtil.read(IOUtil.java:197)~[na:1.7.0\u51] 在sun.nio.ch.socketchannelmp.read(socketchannelmp.java:379)~[na:1.7.0\u 51] 在org.apache.http.nio.reactor.ssl.SSLIOSession.receiveEncryptedData(SSLIOSession.java:449)~[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:503)~[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:122)~[httpcore-nio-4.4.1.jar:4.4.1] 位于org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:164)[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:339)[httpcore-nio-4.4.1.jar:4.4.1] 位于org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:317)[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:278)[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)[httpcore-nio-4.4.1.jar:4.4.1] 在org.apache.http.impl.nio.reactor.AbstractMultiWorkeriorreactor$Worker.run(AbstractMultiWorkeriorreactor.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);
        }
    

    我发现org.apache.http.protocol.responseCONTROL带有代码

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

    此状态代码再现了我的问题。

    连接重置可能是由以下原因引起的。请尝试最新版本,看看是否解决了问题。

    如果响应状态为非2xx,您是否会使用消息内容?否,只有在服务器设置应答状态代码400时才会出现这种情况。我用200,401,402代码测试,正常工作。问题只存在于400个错误代码中。我必须补充一些信息:400代码的问题只存在于非空实体。若服务器并没有设置实体或设置空实体,那个么它工作正常。你们是否使用响应消息的内容?是的,我使用客户端代码为400的响应消息的内容。在客户端正确接收实体。问题只出现在服务器端的异常中。生成服务器答案的代码在我的第一篇文章的“URL Hander Code”块中。你确定吗?在您的示例代码中没有这方面的证据,只有“带有响应的一些后续操作”注释。客户端上的连接重置通常发生在客户端认为底层连接不安全,无法重复使用时,在大多数情况下,如果响应消息仍有未使用的内容,就会发生这种情况
        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);
            }
        }
    
            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;
        }