奇怪的SocketExceptions:连接重置和连接超时
我有一个 Java TCP 服务器和一个 Android TCP 客户端。服务器等待请求,然后将 50MB 数据发送到 Android 客户端(客户端通过循环数组读取数据并覆盖数据,因此数据不会保存在手机上。)一切工作正常,但客户端有时会崩溃这样:
java.net.SocketException: Connection timed out
服务器得到这个:
java.net.SocketException: connection reset
客户端循环读取,直到收到所有数据(我允许它在一次调用中读取的最大数据是1.5MB。
服务器像这样发送:
connectionSocket.getOutputStream().write(new byte[1024*1024*10*5]);
我正在循环客户端并尝试进行 5-10 次传输,这样我就可以测量电池寿命,但我很少成功完成 3 次 50MB 传输,我真的很茫然……我愿意发布的设置非常简单。代码是否有帮助。
这是 adb logcat 在崩溃时对 android 所说的内容:
...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}
这是服务器异常:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
连接断开的原因有多种,从基础设施(正如丹指出的那样)到设备进入睡眠状态。您可能想尝试请求唤醒锁,看看这是否有帮助。此外,通过随机按下触摸屏来阻止设备进入睡眠状态,可以查看这是否与睡眠有关。
另一方面,如果您只是捕获异常并立即重新连接并重试,那么您的测量结果不应偏离太多。您可能还想尝试 UDP 而不是 TCP(不可能超时)。但请务必监控吞吐量是否下降。
There are various reasons why the connection drops, ranging from the infrastructure (as Dan pointed out) to the device going to sleep. You might want to try requesting a wakelock and see if this helps. Also, by randomly pressing the touch screen to keep the device from sleeping could see if this is sleep-related.
On the other hand, if you just catch the Exception and immediately reconnect and retry, your measurements shouldn't be off by too much. You might also want to try UDP instead of TCP (no timeouts possible). Be sure to monitor if the throughput drops though.
我遇到了同样的问题,因为我下载了大量数据,需要 10 多分钟。当设备进入睡眠状态时,我收到
java.net.SocketException:连接超时
。我尝试了@Michael 提出的解决方案,在下载过程中使用
WakeLock
。这并没有解决我的全部问题,因为如果用户按下电源按钮,我也会遇到同样的问题。如果没有按下它,那是因为你阻止 Android 使用 WakeLock 进入睡眠状态,并且 Wifi 没有关闭...最后,我发现问题不在于 CPU 睡眠,而在于 wifi屏幕关闭时即关闭。所以我使用了 WifiLock 并解决了问题!
我使用 WakeLocks 的代码如下所示(当然,我在 AsyncTask 中完成实际工作 - 将其视为伪代码 - ):
您将需要AndroidManifest 中的以下权限:
I was experiencing the same problem, as I do a heavy data download that takes over 10 minutes. When the device went to sleep I got the
java.net.SocketException: Connection timed out
.I tried the solution stated by @Michael, using a
WakeLock
during the download. That not fixed the full problem for me, because if the user pressed the power button I was experiencing the same issue. If it was not pressed that worked because you were preventing Android to sleep with theWakeLock
and Wifi was not turned off...Finally, I came across that the problem was not the CPU sleeping it was that wifi is switched off when the screen turns off. So I used a WifiLock and that fixed the problem!
My code to work with WakeLocks look like (of course, I do the actual work in an AsyncTask -take it as pseudocode-):
You will need the following permission in your AndroidManifest:
只是猜测,但我不认为这是你的代码;我认为这是一个网络问题。我知道一些 WiFi 路由器(*咳嗽* Linksys *咳嗽*) 无法一次处理这么多数据。尝试禁用 WiFi 并使用 3G 进行测试。或者,由于您的目的是测试电池寿命而不是吞吐量,请尝试将数据写入分成较小的块,每个块之间有短暂的暂停(例如,100K 块,延迟约为 10 到 100 毫秒。)这可能测试结果会略有偏差,但您可以通过考虑这些(可能是空闲)暂停的总持续时间内的电池消耗来轻松解决这一问题。
Just guessing, but I don't think it's your code; I think it's a network issue. I've known some WiFi routers (*cough* Linksys *cough*) that had trouble handling that much data at one time. Try disabling WiFi and testing with 3G. Or, since your purpose is to test battery life and not throughput, try breaking up the data writes into smaller chunks, with a brief pause between each chunk (say, 100K chunks, with delays of somewhere around 10 to 100 ms.) This may skew your test results a bit, but you can account for that easily enough by factoring in the battery consumption during the total duration of those (presumably idle) pauses.
增加连接超时来解决我的问题。默认值为 10 秒。
OkHttpClient.Builder 构建器 = new OkHttpClient.Builder();
builder.connectTimeout(15, TimeUnit.SECONDS);
Increase connect timeout to solve my problem. The default value is 10 seconds.
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(15, TimeUnit.SECONDS);