快速構(gòu)建一個(gè)用本地網(wǎng)絡(luò)發(fā)送和接收消息的APP
譯文【51CTO.com快譯】本文將創(chuàng)建一個(gè)使用HTTP服務(wù)器在本地網(wǎng)絡(luò)發(fā)送和接收消息的簡(jiǎn)單通信APP。
該應(yīng)用程序需要有一個(gè)簡(jiǎn)單的HTTP服務(wù)器發(fā)送消息:
- 獲取我的本地IP地址
- 嘗試發(fā)送消息到每個(gè)本地IP,如:
GET xxx.xxx.xxx.1/?msg=message
GET xxx.xxx.xxx.2/?msg= message
...
GET xxx.xxx.xxx.254/?msg= message
本地IP地址
我們需要獲取本地IP地址來(lái)發(fā)送消息并創(chuàng)建HttpServer實(shí)例。下面是一個(gè)簡(jiǎn)單的方法:
// Hard coded, needs improvement
Future<String> myLocalIp() async {
final interfaces =
await NetworkInterface.list(type: InternetAddressType.IPv4, includeLinkLocal: true);
return interfaces
.where((e) => e.addresses.first.address.indexOf('192.') == 0)
?.first
?.addresses
?.first
?.address;
}
它返回一個(gè)類似這樣的IP地址:192.168.0.107
我們將使用前三個(gè)字節(jié)向每個(gè)本地IP發(fā)送一個(gè)請(qǐng)求:192.168.0.xxx
HttpServer
為了能夠接收請(qǐng)求,我們需要使用我們的本地IP和從1024到65353的任何端口創(chuàng)建一個(gè)HttpServer實(shí)例。
Future<void> startServe() async {
final ip = await myLocalIp();
var server = await HttpServer.bind(ip, 8080);
await for (HttpRequest request in server) {
_handleRequest(request);
request.response.write('Ok');
await request.response.close();
}
}
當(dāng)我們收到一個(gè)請(qǐng)求時(shí),我們返回' Ok '。要檢查它是否有效,可以使用這個(gè)鏈接:http://{your local IP}:8080
你應(yīng)該會(huì)看到Ok消息。
在iOS或Android上檢查之前,需要添加權(quán)限。
添加到iOS *info.plist*文件:
<key>NSAppTransportSecurity</key>
<dict><key>NSAllowsArbitraryLoads</key><true/></dict>
添加到*AndroidManifest.xml*文件:
<uses-permission android:name="android.permission.INTERNET" />
處理請(qǐng)求
為了簡(jiǎn)單起見,我們將使用GET方法并使用查詢參數(shù)來(lái)發(fā)送這樣的消息:
http://{local IP}:8080?msg=message&ipip=ip
如果請(qǐng)求有msg和ip這樣的參數(shù),我們將這些值添加到我們的消息列表中,并調(diào)用setState或notify在屏幕上顯示該列表:
void _handleRequest(HttpRequest request) {
final msg = request.uri.queryParameters['msg'];
final from = request.uri.queryParameters['ip'];
if (msg != null) {
messages.insert(0, [from, msg]);
// set state or update
}
}
發(fā)送消息
我們必須把信息發(fā)送到每一個(gè)本地IP。我們可以使用本地IP地址來(lái)獲得前三個(gè)字節(jié),并由此建立本地IP地址列表:
void sendMessage(String msg) async {
final ip = await myLocalIp();
final threeOctet = ip.substring(0, ip.lastIndexOf('.'));
for (var i = 1; i < 200; i++) {
_sendRequest('$threeOctet.$i', "?ip=$ip&msg=$msg");
}
}
void _sendRequest(String to, String path) async {
final client = HttpClient();
client.connectionTimeout = const Duration(seconds: 2);
try {
final resp = await client.get(to, 8080, path);
resp.close();
} catch (e) {}
}
在本例中,它只將消息發(fā)送到從x.x.x.1到x.x.x.199的IP地址上,但理論上,我們可以從1發(fā)送到255。
現(xiàn)在,我們可以向活躍的本地設(shè)備發(fā)送信息。左下方的圖片是一個(gè)物理的iOS設(shè)備,右邊的是一個(gè)macOS桌面應(yīng)用程序。雖它們有不同的本地IP地址,但你可以看到他們可以互相發(fā)送消息。
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】