0

Ice CreamSandwichからJellyBeanにアップグレードしてから、クライアント(Galaxy Nexus)とカスタムサーバーの間でタイミングの問題が発生しているようです。一般的なフローは次のとおりです。

  1. クライアントがソケットを開き、サーバーにHTTP取得を発行します
  2. サーバーは受け入れ、新しいスレッドを開始し、HTTPヘッダーと200OKで応答します。
  3. サーバーは(バイナリ)ファイルをソケットに書き込みます。
  4. クライアントはソケットからデータを読み取り、ファイルに保存します。
  5. サーバースレッドがすべてのデータを書き込んだ後、ソケットを閉じて終了します

これは、JellyBeanが更新される前の過去数か月にわたってうまく機能していました。更新以降、バイナリ転送は約70%の時間成功します。'serverSocket.getInputStream()。read'がストリームの終わりに到達したことを示す-1を返すと、残りの30%は失敗します。データが読み取られておらず、エラー例外が発生しておらず、logcatにも何もありません。

手順5でサーバーの動作を変更すると、タイミングの問題が発生する可能性があります。書き込み後にスレッドがソケットを閉じていましたが、問題が観察されました。ソケットを閉じて削除し、書き込み後にスレッドを終了し、最終的にOSにソケットを閉じさせると、常に機能しているように見えます。

tcpdumpとWireSharkを使用して、成功した場合と失敗した場合の両方でパケットを調べました。失敗した場合、ソケットは数ミリ秒で閉じられますが、成功した場合、ソケットは1/4秒以上閉じられます。これの正味は、ソケットのクローズで発生する遅延により、成功の可能性が高まることです。

この問題を引き起こすために私たちが行っている可能性のある提案や、問題を絞り込む方法についての提案があれば、遠慮なく対応してください。必要に応じてコードサンプルを追加できます。

4

1 に答える 1

-1

サーバーが接続を閉じるように要求すると、ソケットがすぐに閉じられるようです。たぶん、デフォルトの ocket linger の時間がバージョン間で変更されました???

以下を使用してソケットの残留時間を設定してみてください。

socket.setSoLinger(boolean on, int timeout);

一部のデータがまだ送信を待っている場合、チャネルを閉じる前にサーバーをしばらく待機させます。

これで解決しない場合は、上記のフローを次のように変更できます。

...

4.クライアントはソケットからデータを読み取り、ファイルに保存します。

5.クライアントがサーバーに確認を送信します。

6.サーバーの接続を閉じます。

--編集済み-- 終了確認のために追加の TCP データ パケットを送信せずに上記を達成するための適切な方法は次のとおりです。

サーバーがソケット呼び出しへの書き込みを終了すると:

socket.shutdownOutput();

クライアントの socket.read() が -1 を返すと、クライアントは次のように呼び出します。

socket.close();

これにより、すべてのデータが送信されたことがクライアントに通知され、送信者はソケット クロージャ プロトコルが完了するまで待機します。

于 2012-10-07T01:23:58.587 に答える