安卓如何处理没有互联网连接的物联网设备

25

我正在尝试构建一个项目,其中必须通过Wifi从智能手机驾驶IoT设备。

该设备集成了SPWF01 Wifi模块,并配置为WEP安全类型的访问点(没有Internet访问)。在此访问点配置上,我们还有一个TCP套接字服务器来拦截智能手机通信。

在智能手机端,我们有部分代码用于扫描并连接到我们设备的访问点(虽然工作正常,但由于没有Internet访问,Wi-Fi图标上出现感叹号)。连接后,我们启动客户端套接字,该套接字连接到我们IoT设备上的服务器(服务器套接字的IP地址实际上是访问点的网关)。这里出现了问题,因为客户端套接字无法启动。以下是代码:

public void SocketInit(String ip, int port) throws IOException {
    InetAddress addr = InetAddress.getByName(ip);
    SocketAddress sockaddr = new InetSocketAddress(addr, port);
    nsocket = new Socket();
    nsocket.setReuseAddress(true);       
    nsocket.setTcpNoDelay(false);
    nsocket.setReceiveBufferSize(700);   //Must be less than 730byte witch is the module buffer
    nsocket.setSendBufferSize(700);
    nsocket.connect(sockaddr, 5000);     //5 second connection timeout
}

这里是我收到的异常:

java.net.SocketException: socket failed: ENONET (Machine is not on the network)

甚至在达到nsocket.connect()之前,我就遇到了这个错误,准确地说是在setReuseAddress上。

由于我得到的异常是ENONET,我认为这一定是因为接入点没有互联网访问权限,所以我使用了这里提供的解决方案进行测试:

adb shell settings put global captive_portal_detection_enabled 0

这是一个没有根访问权限就无法通过编程实现的解决方案,但我想测试一下是否是问题所在。但虽然Wifi图标上的感叹号消失了,客户端套接字仍然给出相同的异常错误。

有人有这种情况的解决方法吗?谢谢您的帮助!


有时候客户端套接字会成功打开,成功率为20次中1次。但当它成功打开后,通常在发送几条消息后会再次抛出异常:

java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)

这是我从智能手机连接到接入点所使用的代码:

    WifiConfiguration wc=new WifiConfiguration();
    wc.SSID= host;
    wc.status = WifiConfiguration.Status.ENABLED;
    wc.priority = 40;
    wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
    wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
    wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
    wc.allowedGroupCiphers.clear();
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
    wc.wepKeys[0] = password;
    wc.wepTxKeyIndex = 0;

    int netId = mainWifi.addNetwork(wc);
    try {
        //mainWifi.setWifiEnabled(true);
        mainWifi.disconnect();
        mainWifi.enableNetwork(netId, true);
        mainWifi.reconnect();

        startConnectionCheck = true;
        System.out.println("enabled network");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println(e.getMessage());
    }

访问点的安全类型为WEP。这是因为Wifi模块无法实现WPA。


在Marshmallow上进行的测试。


你能从电脑或智能手机上ping这个设备吗? - u354356007
是的,我尝试过在智能手机上使用“fing”应用程序,它可以正常工作。 - Starivore
尝试在启用wifi的智能手机上关闭“数据传输”设置,然后尝试连接设备。有一种可能性是智能手机的默认网关设置不正确。 - u354356007
@Vovanrock2002 我已经尝试关闭移动数据...我忘了提到,但是当它打开时会引起更多麻烦,因为接入点没有互联网,所以连接WiFi时移动数据将保持开启状态。 - Starivore
@Starivore 你找到解决方案了吗? - Lonergan6275
你尝试在应用程序标签下的Android清单文件中添加android:usesCleartextTraffic="true"了吗? - Mert Çalışkanyürek
1个回答

0

我不确定这个问题是否相同。

一段时间以前,我做了一个项目,使用了Java sockets。

在进行初始测试时,我使用本地回环并在同一台计算机上使用端口和多个线程。最终,它足够好,可以在两台计算机之间进行测试。但是我发现它在两台计算机之间无法工作。在关闭网络上的所有防火墙和保护等,并且变得足够绝望以使用直接连接以太网电缆后,我找到了问题所在。

Sockets关心您使用哪个网关。解决方案是我使用网关而不是回环...现在回想起来很明显...

无论如何,你的移动网关、wifi网关和本地回环都可能不同。

这里有一个丑陋的代码片段,希望能给出一些指导,但灵感很少...

Socket socket = null;
try {
    socket = new Socket(ip, port, InetAddress.getLoopbackAddress(), localServerPort);
}
catch (Exception e) {
}
if (socket == null) {
    try {
        socket = new Socket(ip, port, InetAddress.getLocalHost(), localServerPort);
    }
    catch (Exception e) {
    }
}
if(socket == null) {
    throw new Exception("Neither the loop back nor the host could find this sucker.");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接