我的计划是使用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
dnsmasq
和hostapd
服务均为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
崩溃。看来这也是一个完全内部的调用,没有对我实际代码的追溯。