2011-02-06 18 views
3

私は、Java TCPサーバーとAndroid TCPクライアントを持っています。サーバーは要求を待ってからAndroidクライアントに50MBのデータを送ります(アレイをループしてデータを上書きするため、データは電話に保存されません)。すべてうまく動作しますが、ランダムな時間にクライアントがクラッシュします奇妙なSocketExceptions:接続リセットと接続タイムアウト

java.net.SocketException: Connection timed out 

とサーバーがこれを取得します:これで、それは(私はそれが1回の呼び出しで読み取ることができ、最大で1.5メガバイトであるすべてのデータを受信するまで

java.net.SocketException: connection reset 

クライアントは、ループ内で読み込み、

サーバーは次のように送信します。

connectionSocket.getOutputStream().write(new byte[1024*1024*10*5]); 

私はクライアントをループしており、この転送を5-10回実行しようとしていますので、バッテリーの寿命を測定できますが、50MBの転送が3回成功することはめったにありません。私は本当に失われている...私が持っているセットアップは本当に簡単です。私はそれが助けになるならば、コードを掲載して喜んでいます。ここで

...transfering 
D/WifiService( 109): got ACTION_DEVICE_IDLE 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
V/WifiMonitor( 109): Event [CTRL-EVENT-STATE-CHANGE id=1 state=8] 
V/WifiStateTracker( 109): Changing supplicant state: COMPLETED ==> DORMANT 
D/WifiStateTracker( 109): Reset connections and stopping DHCP 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
E/wpa_supplicant( 209): Set_key: Wrong Key 
V/WifiMonitor( 109): Event [CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys] 
V/WifiMonitor( 109): Event [CTRL-EVENT-STATE-CHANGE id=-1 state=8] 
D/WifiStateTracker( 109): Disabling interface 
D/NetworkStateTracker( 109): setDetailed state, old =CONNECTED and new state=IDLE 
V/WifiMonitor( 109): Event [CTRL-EVENT-DRIVER-STATE STOPPED] 
V/WifiStateTracker( 109): New network state is DISCONNECTED 
V/WifiStateTracker( 109): Changing supplicant state: DORMANT ==> DORMANT 
D/ConnectivityService( 109): ConnectivityChange for WIFI: DISCONNECTED/IDLE 
D/ConnectivityService( 109): getMobileDataEnabled returning false 
D/ConnectivityService( 109): not failing over to mobile type 0 because Mobile Data Disabled 
D/ConnectivityService( 109): not failing over to mobile type 2 because Mobile Data Disabled 
D/ConnectivityService( 109): not failing over to mobile type 3 because Mobile Data Disabled 
D/ConnectivityService( 109): not failing over to mobile type 4 because Mobile Data Disabled 
D/ConnectivityService( 109): not failing over to mobile type 5 because Mobile Data Disabled 
D/Tethering( 109): Tethering got CONNECTIVITY_ACTION 
D/Tethering( 109): MasterInitialState.processMessage what=3 
E/HierarchicalStateMachine( 109): TetherMaster - unhandledMessage: msg.what=3 
I/ActivityManager( 109): Start proc android.process.media for broadcast com.android.providers.downloads/.DownloadReceiver: pid=793 uid=10004 gids={1015, 2001, 3003} 
D/NetworkLocationProvider( 109): updateNetworkState(): Updating network state to 1 
I/ActivityThread( 793): Publishing provider media: com.android.providers.media.MediaProvider 
V/MediaProvider( 793): Attached volume: internal 
V/MediaProvider( 793): /mnt/sdcard volume ID: 845505849 
V/MediaProvider( 793): Attached volume: external 
I/ActivityThread( 793): Publishing provider downloads: com.android.providers.downloads.DownloadProvider 
I/ActivityThread( 793): Publishing provider drm: com.android.providers.drm.DrmProvider 
I/GTalkService( 243): [ServiceAutoStarter] --- connectivity changed 
I/GTalkService( 243): [ServiceAutoStarter] --- start GTalk service --- 
I/ActivityManager( 109): Start proc com.google.android.apps.uploader for broadcast com.google.android.apps.uploader/.ConnectivityBroadcastReceiver: pid=801 uid=10027 gids={3003} 
D/GTalkService( 243): [GTalkService.1] onStartCommand: found 0 connections, force audit connections... 
D/GoogleLoginService( 243): onBind: Intent { act=android.accounts.AccountAuthenticator cmp=com.google.android.gsf/.loginservice.GoogleLoginService } 
W/GoogleLoginService( 243): Device has no accounts: sending Intent { act=com.google.android.gsf.LOGIN_ACCOUNTS_MISSING } 
D/GTalkService( 243): [GTalkService.25] account missing 
I/ActivityThread( 801): Publishing provider com.google.android.apps.uploader: com.google.android.apps.uploader.UploadsContentProvider 
I/ActivityThread( 801): Publishing provider com.google.photos.provider.Album: com.google.android.apps.uploader.clients.picasa.AlbumProvider 
D/MediaUploader( 801): UploaderApplication.onCreate 
D/MediaUploader( 801): nonWifiLimit=20971520, default=20971520 
I/MediaUploader( 801): No need to wake up 
I/ActivityManager( 109): Process com.google.android.apps.genie.geniewidget (pid 442) has died. 
W/ActivityManager( 109): Scheduling restart of crashed service com.google.android.apps.genie.geniewidget/.GenieRefreshService in 5000ms 
I/IO exception ( 766): ******************** Log Msg IOE java.net.SocketException: Connection timed out 
**W/System.err( 766): java.net.SocketException: Connection timed out 
W/System.err( 766): at org.apache.harmony.luni.platform.OSNetworkSystem.readSocketImpl(Native Method) 
W/System.err( 766): at org.apache.harmony.luni.platform.OSNetworkSystem.read(OSNetworkSystem.java:358) 
W/System.err( 766): at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:561) 
W/System.err( 766): at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:88) 
W/System.err( 766): at com.mdog.datareceive.Receive$1.onReceive(Receive.java:71) 
W/System.err( 766): at android.app.ActivityThread$PackageInfo$ReceiverDispatcher$Args.run(ActivityThread.java:892) 
W/System.err( 766): at android.os.Handler.handleCallback(Handler.java:587) 
W/System.err( 766): at android.os.Handler.dispatchMessage(Handler.java:92) 
W/System.err( 766): at android.os.Looper.loop(Looper.java:123) 
W/System.err( 766): at android.app.ActivityThread.main(ActivityThread.java:4627) 
W/System.err( 766): at java.lang.reflect.Method.invokeNative(Native Method) 
W/System.err( 766): at java.lang.reflect.Method.invoke(Method.java:521) 
W/System.err( 766): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
W/System.err( 766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
W/System.err( 766): at dalvik.system.NativeStart.main(Native Method)** 
I/ActivityManager( 109): Start proc com.google.android.apps.genie.geniewidget for service com.google.android.apps.genie.geniewidget/.GenieRefreshService: pid=811 uid=10031 gids={3003, 1015} 

は、サーバーの例外である:ここで

は、adbのlogcatがクラッシュでアンドロイドのための言っていることである

Exception in thread "main" java.net.SocketException: Connection reset 
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:96) 
    at java.net.SocketOutputStream.write(SocketOutputStream.java:124) 
    at com.mdog.tcpserver.ServerDriver.main(ServerDriver.java:55) 

答えて

2

インフラストラクチャ(Danが指摘するように)からスリープ状態になるデバイスまで、接続が低下する理由はさまざまです。 wakelockをリクエストして、これが役立つかどうか確認してみてください。また、デバイスがスリープ状態にならないようにタッチスクリーンをランダムに押すことで、これが睡眠関連であるかどうかを確認することができます。

一方、例外を検出してすぐに再接続して再試行すると、測定値があまりにも大きくなることはありません。また、TCPの代わりにUDPを試したいかもしれません(タイムアウトはありません)。スループットが低下するかどうかは必ず確認してください。

+0

こんにちは、私はあなたがウォークロックを拡大できることを望んでいたのですか? Androidは私にとって初めてのものです。私はクライアントに長時間の睡眠(2〜7秒)をさせて睡眠をとらせてもらい、無線LANラジオを寝かせることを望んでいます。これが私がエネルギーを節約しようとしているところです。 wifiを目覚めさせずにこのウェイクロックを要求することは可能ですか? – Michael

+0

いいえ、ワockロックはまったく逆です。あなたは目を覚まし、眠らないようにシステムに頼みます。ラジオがスリープ状態になると、接続に苦しむべきではありませんが、私はこれに賭けません。これは、携帯電話やAndroidのバージョンにも依存する可能性があります。正直言って、私はあなたが達成したいと思っているものでまだ少し混乱しています:)とにかく、接続が失敗したときに再接続する準備ができているのは良いスタイルですが、これがベンチマーク/テストの場合はおそらく残忍で、ポイント。がんばろう! –

+0

私はあなたが2つのバッファ、TCPバッファとアプリケーションバッファを持っているように、転送中に無線をスリープさせることによって、長いデータ転送中にエネルギーを節約しようとしています。あなたは、アプリケーションのバッファをいっぱいにしてから、TCPから読み込みを停止して、最終的にはTCPバッファがいっぱいになると、無線がスリープ状態になる可能性があります。 残念ながら私は500MBの転送を完了することができないようです。私は今、wakelockを試しています。それが画面上に残っていれば問題ありませんが、wifiが眠ってしまうのを防ぐなら問題です。 – Michael

0

ちょうど推測するが、私はそれはあなたのコードだとは思いません。私はそれがネットワークの問題だと思う。私はいくつかのWiFiルータ(* Cough * Linksys * cough *)を知っていたので、一度に多くのデータを扱うことができませんでした。 WiFiを無効にして3Gでテストしてみてください。または、あなたの目的はスループットではなくバッテリーの寿命をテストすることなので、各チャンク間に短い休止時間を置いて、小さなチャンクにデータ書き込みを分割してみてください(たとえば100Kチャンク、約10〜100msの遅延)。テスト結果を少し歪ませることができますが、それらの(おそらくアイドル状態の)ポーズの合計持続時間中にバッテリー消費を考慮することで、簡単に十分に説明することができます。

+0

こんにちはダン、私はサーバーを250KB/sに送信して12.5KBを50ms間隔で送信しました。私もクライアントが160KB/sで読んでいて、まだクラッシュしています(たくさん読んでから7秒間スリープします)。今私は、クライアントがサーバーが行う前に例外を投げているので、クライアント側の問題を考えています。 – Michael

+0

@Michael:明確にするために、サーバーを絞ってテストしましたが、クライアント(つまり、クライアントができるだけ早くソケットからデータを取得する)に変更はありませんでしたか?また、例外は同じですか?サーバーが例外をスローするにはどのくらい時間がかかりますか? –

+0

ええ、サーバーがスロットルを戻して、クライアントの読み取り速度が最大でも(クライアントで)例外がスローされます。クライアントは "Connection timed out"例外をスローし、次にいくつかの "Network Unreachable"例外をスローします。クライアントが例外をスローしてから数分後にサーバーは「ホストへのルートなし」例外をスローしますが、クライアントと同時にクラッシュすることはありません。 kreadによって提案されたwakelockは、すべての状況下での例外を防ぎますが、ウォークロックは悪いと言われています。私は私の測定のために無線LANを隔離することを望んでいました。 – Michael

1

重大なデータのダウンロードに10分以上かかるため、同じ問題が発生していました。デバイスがスリープ状態になったとき、私はjava.net.SocketException: Connection timed outを得ました。

ダウンロード中にWakeLockを使用して、@Michaelが述べた解決策を試しました。ユーザーが電源ボタンを押した場合、私は同じ問題が発生していたので、それは私のために完全な問題を修正していません。 WakeLockでAndroidをスリープ状態にしていて、Wifiがオフになっていないため、Androidが眠らないようにしていたため、うまくいきました。

最後に、問題はCPUがスリープしていないことでした。画面が消灯したときに表示されます。だから私はWifiLockを使い、問題を修正しました!

WakeLocksで動作するように私のコードは、(もちろん、私はAsyncTaskの実際の仕事はpseudocode-としてそれを-takeん)のようになります。

WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE); 
WifiLock wifiLock = wifiManager.createWifiLock("long_download"); 
wifiLock.acquire(); 
// Do the heavy work in background 
wifiLock.release(); 

あなたのAndroidManifestに次の権限が必要になります。

<uses-permission android:name="android.permission.WAKE_LOCK"/>