java - Why is android HttpURLConnection not sending back FIN? -
from android app wanted post data server , response back, process send , request. since continuous communication until no more response process, prefer go httpurlconnection
http.keepalive = true
.
and attempt reuse socket successful, problems facing are:
- i trying initiate close client (android app), since if termination starts server server goes
time_wait
state. , don't want server go state preferred client initiate termination. unfortunately find no suitable wayhttpurlconnection
- after hours of searching gave on doing above attempt , went initiating close server based on
keepalivetimeout
, when server sendsfin
, client respondsack
, because of connection held onfin_wait_2
in server ,close_wait
in agent.
source code:
private httpstatus communicatewithmdmserver(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) { mdmlogger.error("failed send data server url provided not valid "+ e.getmessage()+"\n"); e.printstacktrace(); } catch (ioexception e) { mdmlogger.error("failed send status server : ioexception "+ e.getmessage()+"\n"+e.getstacktrace()); e.printstacktrace(); readerrorstreamandprint(connection); } connection.disconnect(); return status; } /** * api close connection, calling not force connection shutdown * work based on connection header set. * @param connection */ public void closeconnection(){ if(connection != null){ connection.disconnect(); } } /** * used initialize httpurlconnection given url * properties required connection preset here * connection time out : 20 seconds * connection type : keep alive * content type : application/json;charset=utf-8 * , certificates evaluated valid.[ todo 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 post data given connection * call api close @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 read error stream , 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; } mdmlogger.error("errorstream says "+responsedata); } catch (ioexception ioe) { mdmlogger.debug("exception on reading errorstream"); } } /** * api read data given connection , return {@code com.manageengine.mdm.framework.communication.httpstatus} * call api close @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(); mdmlogger.info("response code: "+responsecode); inputstream instream = connection.getinputstream(); mdmlogger.info("response header: "+connection.getheaderfields()); string responsedata = ""; if (responsecode == httpurlconnection.http_ok) { responsedata = readstreamasstring(instream); status.setstatus(http_status_success); status.seturldatabuffer(responsedata); mdmlogger.info("communicatewithmdmserver : response \n" + status.geturldatabuffer()); mdmlogger.info("successfully send data server , received success response "); } else { status.setstatus(http_status_failure); mdmlogger.error("data sent failed response , response code : " + responsecode); } instream.close(); return status; } /** * read inputstream string until eof * call api 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(); }
can help?
when use http.keepalive = true
connections start recycled, in connection pool, , kept open. if server closes connection it's still listening , client still thinks can send data. after all, server's fin
says server not send more data.
since internal logic of connection pool inaccessible have little control. nevertheless, use https
, have open window lower layers , can gain access created socket
through httpsurlconnection.setsslsocketfactory(sslsocketfactory)
.
you can create wrapper default factory (sslsocketfactory.getdefault()
) allows close socket
. simplification bellow:
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(); } ... }
when close underlying socket connection should not eligible recycling , discarded. if closelastsocket
, disconnect
connection should not go pool , if other way around connection should discarded when create new connection.
Comments
Post a Comment