我試圖做的事:從HttpClient的Httpcomponents的HttpCore和HttpClient的HTTP_STATUS 400
- 發送請求(基於HttpComponents的HttpClient 4.5)。
- 在HttpServer中接收該請求(基於HttpComponents HttpCore 4.4.1)。
- 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);
}
}
您是否在使用非2xx狀態的情況下使用郵件內容? – oleg
不,這種情況只有在服務器設置回答狀態代碼400時纔會發生。我用200,401,402代碼進行了測試,結果正常。問題僅在400錯誤代碼中。我必須添加一些信息:400代碼的問題只存在於非空實體中。如果服務器沒有設置實體或設置空實體,那麼它工作正常。 – lanmaster
您是否使用了響應消息的內容? – oleg