Application Engine: Hold Socket Open for more than 2 minutes

Use connections from a trusted App Engine tester to connect to APNS. Writing to the socket is working fine.

But the problem is that Socket gets a fix after 2 minutes of inactivity. The Trusted Tester website says that any socket operation holds the socket for 2 minutes. It is best to keep the socket open until APNS decides to close the connection.

After you have almost completely applied all the methods of the Socket API without recording the output stream, the Socket closes after 2 minutes no matter what. What did I miss?

Deployed on a Java server.

+4
source share
3 answers

You cannot keep a socket connected to APNS artificially open; without sending actual push notifications. The only way to keep it open is to send some arbitrary data / bytes, but this will immediately close the socket; APNS closes the connection as soon as it detects something that does not comply with the protocol, that is, something that is not the actual push notification.

SO_KEEPALIVE

What about SO_KEEPALIVE ? App Engine clearly says that it is supported. I think it just means that it will not throw an exception when you call Socket.setKeepAlive(true) ; calls wanted to set socket parameters. Exceptions not implemented before. Even if you enable keep-alive, your socket will be restored (closed) if you do not send something more than 2 minutes; at least on the App Engine.

Actually, this is not a big surprise. RFC1122 , which indicates that TCP Keep Alive explicitly indicates that TCP Keep Alives should not be sent more than once every two hours, and then only necessary if there was no other traffic. Although, he also says that this interval should also be customizable, the java.net.Socket API that you could use to configure it (most likely because it is very OS dependent) does not exist, and I doubt that It will be installed for 2 minutes in App Engine.

SO_TIMEOUT

What about SO_TIMEOUT ? This is for something completely different. The javadoc Socket.setSoTimeout() says:

Enable / disable SO_TIMEOUT with the specified timeout in milliseconds. If this parameter is set to a non-zero timeout, the read () call in the InputStream associated with this Socket will be blocked only for this amount of time. If the timeout expires, a java.net.SocketTimeoutException is thrown, although Socket is still valid. The option must be activated before the lock operation is entered. The timeout must be> 0. A zero timeout is interpreted as an infinite timeout.

That is, when read() blocked for too long because there is nothing to read, you can say "well, I don’t want to wait (block) anymore, but do something else instead." This will not help with our 2 minutes problem.

What then?

The only way around this problem is to detect when the connection will be restored / closed, and then throw it away and open a new connection. And there is a library that supports just that.

Check out java-apns-gae .

This is an open source Java APNS library that has been specifically designed to work (and use) with the Google App Engine.

https://github.com/ZsoltSafrany/java-apns-gae

+1
source

Have you tried getSoLinger ()? It can be getSocketOpt, which is working (sort of) at the moment, and can reset a 2 minute timeout. Theoretically, also doing read with zero byte, but I'm not sure if you try this, use this method in the input stream.

public int read (byte b [], int off, int len)

If these suggestions do not work, please report a problem with the issue tracker in App Engine.

Some other fixes will appear, for example. using socket options, etc.

0
source

Use getpeername() .

From https://developers.google.com/appengine/docs/java/sockets/overview ...

Sockets can be restored after 2 minutes of inactivity; any socket (e.g. getpeername) retains a live socket for a further 2 minutes . (Note that you cannot choose between several available sockets, because it requires a java.nio.SocketChannel, which is not currently supported.)

0
source

All Articles