APNS に接続されたソケットを人為的に開いたままにすることはできません。実際のプッシュ通知を送信することなく。それを開いたままにしておく唯一の方法は、任意のデータ/バイトを送信することですが、それはソケットの即時閉鎖につながります。APNS は、プロトコルに準拠していないもの、つまり実際のプッシュ通知ではないものを検出するとすぐに接続を閉じます。
SO_KEEPALIVE
どうSO_KEEPALIVE
ですか?App Engine は、サポートされていることを明示的に示しています。を呼び出したときに例外がスローされないことを意味していると思いますSocket.setKeepAlive(true)
。呼び出しは、以前に実装されていない例外を発生させたソケット オプションを設定する必要がありました。キープアライブを有効にしても、2 分以上何かを送信しない場合、ソケットは再利用 (クローズ) されます。少なくとも今のところ App Engine では。
実際、それは大きな驚きではありません。TCP キープ アライブを指定するRFC1122は、TCP キープ アライブが 2 時間に 1 回以上送信されるべきではないと明示的に述べており、他のトラフィックがない場合にのみ必要です。また、この間隔も構成可能でなければならないと言っていますが、それjava.net.Socket
を構成するために使用できる API はありません (おそらく OS に大きく依存しているため)。App Engine で 2 分に設定されるとは思えません。
SO_TIMEOUT
どうSO_TIMEOUT
ですか?それはまったく別のもののためです。状態の javadoc Socket.setSoTimeout()
:
ミリ秒単位で指定されたタイムアウトで SO_TIMEOUT を有効/無効にします。このオプションをゼロ以外のタイムアウトに設定すると、この Socket に関連付けられた InputStream での read() 呼び出しは、この時間だけブロックされます。タイムアウトになると、Socket は引き続き有効ですが、java.net.SocketTimeoutException が発生します。このオプションを有効にするには、ブロッキング操作に入る前に有効にする必要があります。タイムアウトは > 0 でなければなりません。ゼロのタイムアウトは、無限のタイムアウトと解釈されます。
つまり、read()
読むものが何もないために が長時間ブロックしている場合、「わかりました。もう (ブロック) 待ちたくないので、代わりに別のことをしましょう」と言うことができます。「2分」の問題には役に立ちません。
What then?
この問題を回避できる唯一の方法は、接続が再利用/閉じられたことを検出し、それを破棄して新しい接続を開くことです。そして、まさにそれをサポートするライブラリがあります。
チェックアウトしてくださいjava-apns-gae
。
これは、Google App Engine で動作 (および使用) するように特別に設計されたオープンソースの Java APNS ライブラリです。
https://github.com/ZsoltSafrany/java-apns-gae