使用Pi 3作为接入点通过网络套接字连接Android和Pi 3

时间:2018-10-01 18:03:00

标签: android python sockets raspberry-pi

我的计划是使用wlan0设置的接口hostapd在Pi 3上创建一个接入点。我运行命令hostapd /etc/hostapd/hostapd.conf来启动网络,然后我想用Android连接到该网络并设置一个套接字。

当前,网络可以在Pi 3上正常运行,但是在Android上创建套接字的情况却很复杂

java.net.ConnectException: failed to connect to /192.168.42.1 (port 80) after 500ms: connect failed: ENETUNREACH (Network is unreachable)

我正在使用Pi的wlan0的IP创建您所看到的套接字(在Android代码上)。我将发布Pi的Python脚本的输出以及有关网络的一些信息。

我在Pi 3(服务器)上有以下Python 3代码:

import socket
import os

os.system('hostapd /etc/hostapd/hostapd.conf &')
print('started access point service')

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('192.168.42.1', 80))
serversocket.listen(1)

connection, address = serversocket.accept()

b = connection.recv(1024)
print(b)

serversocket.close()
connection.shutdown(socket.SHUT_WR)
connection.close()

有关wifi套接字连接(客户端)的Android代码。使用其SSID加入网络:

        // enable Wifi
        wifiManager.setWifiEnabled(true);

        // connect to the network access point created by the Pi 3
        WifiConfiguration wifiConfiguration = new WifiConfiguration();
        wifiConfiguration.SSID = "\"" + blackBoxSSID + "\"";
        wifiConfiguration.preSharedKey = "\"" + blackBoxNetworkPassword + "\"";
        wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
        wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);

        int netID = wifiManager.addNetwork(wifiConfiguration);
        if (netID == -1) {
            netID = getExistingNetworkID(wifiConfiguration.SSID);
        }

        wifiManager.disconnect();
        wifiManager.enableNetwork(netID, true);
        wifiManager.reconnect();

        WifiInfo wifiInfo = wifiManager.getConnectionInfo();

        Log.d(TAG, "current netID " + netID + ", current SSID " + wifiInfo.getSSID());
        Log.d(TAG, "current IP of wifi device: " + wifiInfo.getIpAddress() + ", HW address: " + wifiInfo.getMacAddress());

        // start the server socket process
        startServerSocket();

助手功能:

    private void startServerSocket() {
            Log.i(TAG, "Starting server socket thread");
            Thread serverSocketThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Socket socket = new Socket();
                        socket.bind(null);
                        socket.connect(new InetSocketAddress("192.168.42.1", 80), 500);
                        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                        dataOutputStream.writeBytes("Hello black box");
                        dataOutputStream.writeBytes("Hello black box");
                        dataOutputStream.writeBytes("Hello black box");
                        dataOutputStream.writeBytes("Hello black box");
                        dataOutputStream.writeBytes("Hello black box");
                        dataOutputStream.writeBytes("Hello black box");
                        socket.close();
                    } catch (IOException e) {
                        Log.e(TAG, "Error creating ServerSocket and Socket object:", e);
                    }
                }
            });
            serverSocketThread.start();
            Log.d(TAG, "started server socket thread");
        }

private int getExistingNetworkID(String SSID) {
        WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
        if (configuredNetworks != null) {
            for (WifiConfiguration existingConfig : configuredNetworks) {
                if (existingConfig.SSID.equals(SSID)) {
                    return existingConfig.networkId;
                }
            }
        }
        return -1;
    }

这是清单文件:

<!-- Wifi/Internet-related permissions -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

Android代码返回

current netID 617, current SSID "NetworkName" current IP of wifi device: 0, HW address: <hw address of something but not wlan0>,这意味着正确的网络连接没有问题。

Python代码返回

started access point service
Configuration file: /etc/hostapd/hostapd.conf
Failed to create interface mon.wlan0: -95 (Operation not supported)
wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlan0: Could not connect to kernel driver
Using interface wlan0 with hwaddr <wlan0 hw address> and ssid "NetworkName"
listening on port 80
wlan0: interface state COUNTRY_UPDATE->ENABLED
wlan0: AP-ENABLED 

和我拥有的所有wifi设备都可以看到网络并使用密码进行连接。

有关更多信息,这里是hostapd.conf文件:

interface=wlan0
#driver=nl80211
ssid=Coriolis
country_code=CA
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=password123
wpa_key_mgmt=WPA-PSK
wpa_group_rekey=86400
ieee80211n=1
wpa_pairwise=TKIP
rsn_pairwise=CCMP
wme_enabled=1

对于某些代码段中的缩进感到很抱歉,使用{}代码按钮可以将其插入,如果不删除代码格式,我似乎无法摆脱它。

编辑:

这是/etc/dnsmasq.conf的内容:

interface=wlan0 dhcp-range=192.168.42.2,192.168.42.4,255.255.255.0,24h

dnsmasqhostapd服务均为active (running)

如果我手动转到并选择Wifi,然后使用WPA密码进行连接,则该设备将与Pi 3关联,然后取消关联,然后通过AP-STA-CONNECTED读取pairwise key handshake completed (RSN)。很明显,我的Android代码做得很奇怪。但是这样做会导致应用RuntimeException; unable to instantiate receiver (wifiReceiver - which doesn't exist)ClassNotFoundException: didn't find class (wifiReceiver) on path: DexPathList崩溃。看来这也是一个完全内部的调用,没有对我实际代码的追溯。

0 个答案:

没有答案