使用App Engine Trusted Tester套接字连接到APNS。写入套接字工作正常。
但问题是Socket在2分钟不活动后被收回。它在Trusted Tester网站上说任何套接字操作都会使套接字保持活动状态2分钟。在APNS决定关闭连接之前保持套接字打开更好。
在尝试了几乎所有的Socket API方法之后,无法写入输出流,无论如何,Socket会在2分钟后关闭。我错过了什么?
部署在java后端。
答案 0 :(得分:1)
您不能将连接到APNS的套接字人为打开;没有发送实际推送通知。保持打开的唯一方法是发送一些任意数据/字节,但这会导致套接字立即关闭; APNS一检测到不符合协议的内容即关闭连接,即不是实际的推送通知。
SO_KEEPALIVE
SO_KEEPALIVE
怎么样? App Engine明确表示支持它。我认为这只是意味着当你致电Socket.setKeepAlive(true)
时它不会抛出异常;调用想要设置套接字选项之前没有实现异常。即使您启用keep-alive,如果您不发送超过2分钟的内容,您的套接字也将被回收(关闭);至少在现在的App Engine上。
实际上,这并不是一个大惊喜。指定TCP Keep Alive的RFC1122明确指出TCP Keep Alives不会每两小时发送一次以上,然后,只有在没有其他流量时才需要。虽然,它也说这个间隔也必须是可配置的,但java.net.Socket
上没有可用于配置的API(很可能是因为它依赖于OS),我怀疑它会在App上设置为2分钟发动机。
SO_TIMEOUT
SO_TIMEOUT
怎么样?这是完全不同的东西。 Socket.setSoTimeout()
状态的javadoc:
使用指定的超时启用/禁用SO_TIMEOUT,以毫秒为单位。如果将此选项设置为非零超时,则与此Socket关联的InputStream上的read()调用将仅阻止这段时间。如果超时到期,则引发java.net.SocketTimeoutException,尽管Socket仍然有效。必须在进入阻止操作之前启用该选项才能生效。超时必须> 0.超时为零被解释为无限超时。
也就是说,当read()
阻塞太长时间因为没有什么可读的时候你可以说“好吧,我不想再等待(阻止)了;让我们做其他事情”。这对我们的“2分钟”问题没有帮助。
What then?
解决此问题的唯一方法是:检测何时回收/关闭连接然后将其丢弃并打开新连接。并且有一个库可以完全支持它。
结帐java-apns-gae
。
这是一个开源的Java APNS库,专为在Google App Engine上工作(和使用)而设计。
答案 1 :(得分:0)
你试过getSoLinger()吗?这可能是当前工作(种类)的getSocketOpt,它可能会重置2分钟超时。从理论上讲,也可以进行零字节读取,但我不确定如果你尝试的话,会在输入流上使用这种方法。
public int read(byte b [],int off,int len)
如果这些建议不起作用,请向App Engine问题跟踪器提出问题。
还会有其他一些修复措施,例如:使用套接字选项等。
答案 2 :(得分:0)
使用getpeername()
。
来自https://developers.google.com/appengine/docs/java/sockets/overview ...
在2分钟不活动后,可以回收插座; 任何套接字 operation(例如getpeername)使套接字保持活动状态2 分钟即可。 (请注意,您无法在多个可用之间进行选择 套接字,因为这需要java.nio.SocketChannel,而不是 目前支持。)