Java 为什么android HttpURLConnection没有发送回FIN?
从我的安卓应用程序中,我想将数据发布到服务器并获得响应,处理它,然后发送回并获得另一个请求。由于它是持续的通信,直到对进程没有更多响应为止,我更喜欢使用Java 为什么android HttpURLConnection没有发送回FIN?,java,android,tcp,httpurlconnection,keep-alive,Java,Android,Tcp,Httpurlconnection,Keep Alive,从我的安卓应用程序中,我想将数据发布到服务器并获得响应,处理它,然后发送回并获得另一个请求。由于它是持续的通信,直到对进程没有更多响应为止,我更喜欢使用HttpURLConnectionhttp.keepAlive=true 我尝试重用socket是成功的,但我面临的问题是: 我正在尝试从客户端启动Close(Android应用程序),因为如果 终止从服务器开始,然后服务器转到 等待时间状态。我不希望我的服务器进入那种状态,所以我更希望我的客户端启动终止。但不幸的是 我找不到合适的方法来使用Ht
HttpURLConnection
http.keepAlive=true
我尝试重用socket是成功的,但我面临的问题是:
等待时间
状态。我不希望我的服务器进入那种状态,所以我更希望我的客户端启动终止。但不幸的是
我找不到合适的方法来使用HttpURLConnection
keepalivetimeout
,但当服务器发送FIN
时,客户端只响应
,因为该连接被中断
FIN\u WAIT\u 2
在服务器中,并关闭\u WAIT
在代理中private HttpStatus communicateWithServer(String httpUrl, String dataToSend, boolean keepAlive) {
HttpStatus status = new HttpStatus(HTTP_STATUS_FAILURE);
try {
initializeConnection(httpUrl,keepAlive);
postDataToConnection(connection, dataToSend);
status = readDataFromConnection(connection);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
readErrorStreamAndPrint(connection);
}
connection.disconnect();
return status;
}
/**
* API to close connection, calling this will not force the connection to shutdown
* this will work based on the Connection header set.
* @param connection
*/
public void closeConnection(){
if(connection != null){
connection.disconnect();
}
}
/**
* Used to initialize the HttpURLConnection for the given url
* All properties required for connection are preset here
* Connection Time Out : 20 Seconds
* Connection Type : keep alive
* Content Type : application/json;charset=UTF-8
* And also All certificates will be evaluated as Valid.[ TODO will be removed soon]
* @param httpUrl
* @return
* @throws MalformedURLException
* @throws IOException
*/
private void initializeConnection(String httpUrl, boolean keepAlive) throws MalformedURLException, IOException{
URL url = new URL(httpUrl);
connection = (HttpsURLConnection) url.openConnection();
connection.setConnectTimeout(20000);
connection.setReadTimeout(20000);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST"); //NO I18N
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); //NO I18N
connection.setRequestProperty("Connection", "Keep-Alive"); //NO I18N
}
/**
* API to post data to given connection
* call to this API will close the @OutputStream
* @param connection
* @param data
* @throws IOException
*/
private void postDataToConnection(URLConnection connection , String data) throws IOException{
OutputStream outStream = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream));
writer.write(data);
writer.flush();
writer.close();
outStream.close();
}
/**
* API to read error stream and log
* @param connection
*/
private void readErrorStreamAndPrint(URLConnection connection){
try{
InputStream inStream = ((HttpURLConnection) connection).getErrorStream();
String responseData = "";
String line;
BufferedReader br=new BufferedReader(new InputStreamReader(inStream));
while ((line=br.readLine()) != null) {
responseData+=line;
}
} catch (IOException ioe) {
}
}
/**
* API to read data from given connection and return
* call to this API will close the @InputStream
* @param connection
* @return
* @throws IOException
*/
private HttpStatus readDataFromConnection(URLConnection connection) throws IOException{
HttpStatus status = new HttpStatus(HTTP_STATUS_FAILURE);
int responseCode=((HttpURLConnection) connection).getResponseCode();
InputStream inStream = connection.getInputStream();
String responseData = "";
if (responseCode == HttpURLConnection.HTTP_OK) {
responseData = readStreamAsString(inStream);
status.setStatus(HTTP_STATUS_SUCCESS);
status.setUrlDataBuffer(responseData);
}
else {
status.setStatus(HTTP_STATUS_FAILURE);
}
inStream.close();
return status;
}
/**
* Read the InputStream to String until EOF
* Call to this API will not close @InputStream
* @param inStream
* @return
* @throws IOException
*/
private String readStreamAsString(InputStream inStream) throws IOException{
StringBuilder responseData = new StringBuilder();
String line;
BufferedReader br=new BufferedReader(new InputStreamReader(inStream));
while ((line=br.readLine()) != null) {
responseData.append(line);
}
return responseData.toString();
}
有人能帮忙吗?我发现了一些有趣的想法 以下是有关FIN的一些信息: 在这里,重要的是要理解
connection.disconnect()
不保证触发FIN。从
HttpURLConnection
的文档:
读取响应正文后,应通过调用disconnect()
关闭HttpURLConnection
。
断开连接将释放连接所持有的资源,以便可以关闭或重用这些资源
这里的重点放在梅身上:正如你从上一篇文章中看到的那样
屏幕截图,是服务器决定终止连接
在某个时刻,而不是我们要求断开连接,因为第一个鳍是
由目标而不是源发送。当您使用
http.keepAlive=true
时,连接开始在连接池中循环,并保持打开状态。即使服务器关闭了连接,它仍在侦听,客户端仍认为它可以发送数据。毕竟,服务器的FIN
只是说服务器不会发送更多数据
由于连接池的内部逻辑不可访问,因此您几乎无法控制。尽管如此,当您使用https时,您有一个打开的窗口可以访问较低层,并且可以通过HttpsURLConnection.setsssocketfactory(SSLSocketFactory)
访问创建的套接字
您可以为默认工厂(SSLSocketFactory.getDefault()
)创建一个包装器,该包装器允许关闭套接字。类似于下面的简化:
public class MySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
private Socket last;
public void closeLastSocket() {
if (last != null) {
last.close();
}
}
public Socket createSocket() throws IOException {
return this.last = factory.createSocket();
}
...
}
当您关闭基础套接字时,连接不应符合回收条件,将被丢弃。因此,如果您执行closeLastSocket
和disconnect
操作,则连接甚至不应进入池中,如果您执行其他操作,则只有在创建新连接时,连接才会被丢弃。使用HttpURLConnection执行此操作的合适方法是HttpURLConnection.disconnect().`但这只是一个提示。@EJP我在事务结束时使用了disconnect(),但我没有发现任何区别,请您详细说明一下。