-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Maxim,

On 2/1/16 4:53 AM, Maxim Neshcheret wrote:
> There is such option in my app (heartbeats from server to client)
> but I’m curious why connection becomes stale if I don’t send any
> heartbeats.

Any networking component can decide that a connection has been open
for too long. It could be the OS's TCP/IP stack, a software firewall
on either end, etc. Or the client could have gone to sleep (e.g. OS
sleep mode). Your heartbeats keep it from going to sleep , maybe?

If you want a 10-day connection to stay open, heartbeats are the only
way to do it. Presumably, you can catch the heartbeat failure? Under
that condition, take appropriate action.

- -chris

> On 29/01/16 16:04, "Christoph Nenning"
> <christoph.nenn...@lex-com.net> wrote:
> 
>>> I have a problem with my java application related to HTTP
>>> communication.
>>> 
>>> Application description:
>>> 
>>> 1.      Client – server. Server is running in servlet
>>> container. We use Tomcat.
>>> 
>>> Client use java HTTP library to communicate with the server.
>>> 
>>> 2.      When client establish connection to the server it sends
>>> GET request (keepalive) and server creates AsyncContext for the
>>> client with 10 days timeout.
>>> 
>>> 3.      After connection established server periodically sends
>>> data to the client using AsyncContext and on the client side
>>> there is special thread which reads and processes the data.
>>> 
>>> Client reading thread example:
>>> 
>>> private class GetRunnable implements Runnable {
>>> 
>>> private final HttpURLConnection httpConn; private final
>>> MyConnection myConn;
>>> 
>>> public GetRunnable(final MyConnection myConn) throws 
>>> IOException, AppException { this.myConn = myConn; final String
>>> jSession = myConn.getJSession(); httpConn =
>>> openHttpUrlConnection(false, httpPostTimeout, jSession); 
>>> httpConn.connect(); final int respCode =
>>> httpConn.getResponseCode(); if (respCode !=
>>> HttpURLConnection.HTTP_OK) { String info = "Incorrect response
>>> from server, responseCode:" + respCode + ", message:" +
>> httpConn.getResponseMessage();
>>> log.error(info); throw new AppException(info); } else { 
>>> log.trace("GET connected"); } }
>>> 
>>> @Override public void run() { try (final BufferedReader reader
>>> = new BufferedReader (new
>>> InputStreamReader(httpConn.getInputStream(), "UTF-8")) ) { 
>>> log.info("doGet STARTED"); final Thread t =
>>> Thread.currentThread(); while (!t.isInterrupted()) { 
>>> log.trace("before readline"); final String line =
>>> reader.readLine(); log.trace("after readline: [" + line +
>>> "]");
>>> 
>>> //INFO: DATA PROCESSING HERE } } catch (IOException e) { 
>>> log.error("Error while doGet"); } catch (Throwable e) { 
>>> log.debug("doGet STOPED..."); log.error("Error while read input
>>> msg, do logoff",
>> e);
>>> logoff(); throw e; } log.debug("doGet STOPED..."); 
>>> myCallback.onGetClose(myConn, connInfo); } }
>>> 
>>> Server side code to push data looks like this:
>>> 
>>> protected int sendMsgs(final MyConnection myConn, final String
>>> info) {
>>> 
>>> int res; try { final AsyncContext lAc = _ac; final
>>> ServletRequest req = lAc.getRequest(); if
>>> (!req.isAsyncStarted()) { log.debug("AsyncStarted=false on
>>> begin, uid:" + uid + ", sid:" + sid); return -1; }
>>> 
>>> final ServletResponse res = lAc.getResponse(); 
>>> ServletOutputStream  os = null; final String text =
>>> getData(myConn);
>>> 
>>> if (os == null) os = res.getOutputStream();
>>> 
>>> write2stream(os, text, 0x4000); os.println();
>>> 
>>> if (os != null) os.flush(); } catch(IOException ex) { 
>>> log.error("Notify failed"); } catch (InterruptedException e) { 
>>> log.error("Notify failed"); 
>>> Thread.currentThread().interrupt(); } catch (Throwable e) { 
>>> log.error("Notify failed"); logoff(true); }
>>> 
>>> return res; }
>>> 
>>> public static void write2stream(final OutputStream
>>> outputStream, final String text, int bufferSize) throws
>>> IOException { final CharsetEncoder encoder =
>>> getHttpEncodingCharset ().newEncoder();
>>> 
>>> final int fullLen = text.length(); final int byteBufferSize =
>>> Math.min(bufferSize, fullLen);
>>> 
>>> final int en = (int)(byteBufferSize * (double) 
>>> encoder.maxBytesPerChar()); final byte[] byteArray = new
>>> byte[en];
>>> 
>>> final ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray); final
>>> CharBuffer charBuffer = CharBuffer.wrap(text); for(int pos=0,
>>> len=byteBufferSize; pos < fullLen; pos=len,
>>> len=Math.min(pos+byteBufferSize, fullLen)) {
>>> 
>>> try { final CharBuffer window = charBuffer.subSequence(pos,
>> len);
>>> 
>>> CoderResult res = encoder.encode(window, byteBuffer, true);
>>> 
>>> if (!res.isUnderflow()) res.throwException();
>>> 
>>> res = encoder.flush(byteBuffer);
>>> 
>>> if (!res.isUnderflow()) res.throwException();
>>> 
>>> } catch (final CharacterCodingException x) { throw new
>>> Error(x); }
>>> 
>>> outputStream.write(byteArray, 0, byteBuffer.position());
>>> 
>>> byteBuffer.clear(); encoder.reset(); } }
>>> 
>>> Usually this code works fine but it there is no data from
>>> server to client for 1 day and after 24 hours (can be 16 or 12)
>>> data appears, server cannot send data to the client. In the log
>>> there is no error. It is written that everything flushed but
>>> client still waiting for data in “final String line =
>> reader.readLine();”
>>> When 2nd portion of data is sent by the server, then during
>>> flush I see the following error
>>> 
>>> 2016-01-26 00:00:00,051|INFO |GWNotify-2/50       |ClientAbort 
>>> 2016-01-26 00:00:00,051|TRACE|GWNotify-2/50       | 
>>> ClientAbortException:java.io.IOException: APR error: -32 
>>> org.apache.catalina.connector.ClientAbortException: 
>>> java.io.IOException: APR error: -32 at
>>> org.apache.catalina.connector.OutputBuffer.doFlush 
>>> (OutputBuffer.java:353) ~[catalina.jar:8.0.30] at
>>> org.apache.catalina.connector.OutputBuffer.flush 
>>> (OutputBuffer.java:317) ~[catalina.jar:8.0.30] at 
>>> org.apache.catalina.connector.CoyoteOutputStream.flush 
>>> (CoyoteOutputStream.java:110) ~[catalina.jar:8.0.30]
>>> 
>>> Caused by: java.io.IOException: APR error: -32 at 
>>> org.apache.coyote.http11.InternalAprOutputBuffer.writeToSocket 
>>> (InternalAprOutputBuffer.java:291) ~[tomcat-coyote.jar:8.0.30] 
>>> at 
>>> org.apache.coyote.http11.InternalAprOutputBuffer.writeToSocket 
>>> (InternalAprOutputBuffer.java:244) ~[tomcat-coyote.jar:8.0.30] 
>>> at 
>>> org.apache.coyote.http11.InternalAprOutputBuffer.flushBuffer 
>>> (InternalAprOutputBuffer.java:213) ~[tomcat-coyote.jar:8.0.30] 
>>> at org.apache.coyote.http11.AbstractOutputBuffer.flush 
>>> (AbstractOutputBuffer.java:305) ~[tomcat-coyote.jar:8.0.30] at 
>>> org.apache.coyote.http11.AbstractHttp11Processor.action 
>>> (AbstractHttp11Processor.java:765) ~[tomcat-coyote.jar:8.0.30] 
>>> at org.apache.coyote.Response.action(Response.java: 177)
>>> ~[tomcat-coyote.jar:8.0.30] at
>>> org.apache.catalina.connector.OutputBuffer.doFlush 
>>> (OutputBuffer.java:349) ~[catalina.jar:8.0.30] ... 6 more
>>> 
>>> Finally after I stop server I see that GetRunnable client
>>> thread is still alive and waiting data from the server in
>>> “final String line = reader.readLine();”!!!
>> 
>> 
>> Hi,
>> 
>> I would send some keep-alive data (e.g. current timestamp) maybe
>> once per day or once every 5 hours. The client can just dismiss
>> that data. This might help in some situations but there is no
>> 100% guarantee that it works always.
>> 
>> 
>> Regards, Christoph
>> 
>> 
>> This Email was scanned by Sophos Anti Virus
> 
> 
> ---------------------------------------------------------------------
>
> 
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
> 
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlavk4EACgkQ9CaO5/Lv0PC8SQCgiq7KSXyhgKH37xNI067lLO0C
FoEAn2yZn3uXHVLAz7+Ae/itrYDieyMT
=3LYs
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to