项目场景:
项目场景:AndroidStudio开发一个在安卓工业控制屏上的软件,需要建立webSocket连接,不间断发送传感器数据给服务器
问题描述:
webSocket连接总是会每隔半个小时断开一次,起初以为是代码问题,检查了几遍,服务器代码也检查了,没查出个所以然来
原因分析:
从断开连接时打印出的日志,看不出什么问题,后来在app加入了网络监听功能,每次断开的时候,网络状态也会跟着变换,断开一下,网络马上又恢复,设备连接的公司的WiFi,最后把问题定位到了"路由器DHCP"上面,由于是动态获取IP,所以DHCP会自动续期,导致30分钟断网又重连???
问题排查:
1.在每次断网时记录当前 IP 地址是否有变化,有变化说明确实是DHCP更新了
//NetworkStatusMonitor
/**
* 获取当前设备的本地 IP 地址(如 192.168.x.x)
*/
@SuppressLint("DiscouragedApi")
public static String getIPAddress(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) return "0.0.0.0";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Network network = connectivityManager.getActiveNetwork();
if (network != null) {
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
int ipInt = wifiManager.getConnectionInfo().getIpAddress();
try {
return InetAddress.getByAddress(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array()).getHostAddress();
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
// 移动数据模式下尝试获取本机 IP
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
return "0.0.0.0";
}
//mainActivity
private void registerNetworkReceiver() {
// 初始化网络状态检测
NetworkStatusMonitor.getInstance().init(this);
NetworkStatusMonitor.getInstance().addListener(isAvailable -> runOnUiThread(() -> {
Log.e(TAG, "网络状态变更: " + (isAvailable ? "连接" : "断开"));
String currentIP = NetworkStatusMonitor.getIPAddress(getApplicationContext());
Log.e("CurrentIP", "设备当前 IP: " + currentIP);
if (isAvailable) {
tvNetworkStatus.setText("连接");
tvNetworkStatus.setTextColor(Color.GREEN);
if (signalRManager == null) {
testWebsocket();
} else if (signalRManager.isCanConnected()) {
signalRManager.startConnection();
}
} else {
tvNetworkStatus.setText("断开");
tvNetworkStatus.setTextColor(Color.RED);
}
}));
}
解决问题:
1.设置路由器DHCP
DHCP设置时间长一点,由于公司路由器不知道admin账号密码,所以放弃
2.windows抓包分析 DHCP 租期(没试过)
ipconfig /all
租约获得时间 : ...
租约过期时间 : ...
计算两者之间的时间差就是 DHCP 租期。
3.android设备,使用 adb shell 抓包(没试过)
安装 ADB
连接设备并运行: adb shell
查看当前 IP 和 DHCP 状态 ip addr show
使用 tcpdump 抓包(需要 root) tcpdump -i any port 67 or port 68 -w dhcp.pcap
拷贝到电脑查看 adb pull /sdcard/dhcp.pcap .
使用 Wireshark 打开 dhcp.pcap 文件即可看到完整的 DHCP 请求/响应过程。
4.使用静态 IP 避免频繁断网感知,即使不能更改 DHCP 租期,也可以在 Android 设备上手动设置静态 IP,避免频繁重新获取 IP 地址
5.还不行就把app安装到手机上观察一下或者不连WiFi(使用4G卡)
测试的设备网络不稳定