如何快速构建一个用本地网络发送和接收消息的APP
本文将创建一个使用HTTP服务器在本地网络发送和接收消息的简单通信APP。
该应用程序需要有一个简单的HTTP服务器发送消息:
- 获取我的本地IP地址
 
- 尝试发送消息到每个本地IP,如:
 
GET xxx.xxx.xxx.1/?msg=messageGET xxx.xxx.xxx.2/?msg= message...GET xxx.xxx.xxx.254/?msg= message
本地IP地址
我们需要获取本地IP地址来发送消息并创建HttpServer实例。下面是一个简单的方法:
// Hard coded, needs improvementFuture<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;}
它返回一个类似这样的IP地址:192.168.0.107
我们将使用前三个字节向每个本地IP发送一个请求:192.168.0.xxx
HttpServer
为了能够接收请求,我们需要使用我们的本地IP和从1024到65353的任何端口创建一个HttpServer实例。
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();}}
当我们收到一个请求时,我们返回’ Ok ‘。要检查它是否有效,可以使用这个链接:http://{your local IP}:8080
你应该会看到Ok消息。
在iOS或Android上检查之前,需要添加权限。
添加到iOS info.plist文件:
<key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/></dict>
添加到AndroidManifest.xml文件:
<uses-permission android:name="android.permission.INTERNET" />
处理请求
为了简单起见,我们将使用GET方法并使用查询参数来发送这样的消息:
http://{local IP}:8080?msg=message&ip=ip
如果请求有msg和ip这样的参数,我们将这些值添加到我们的消息列表中,并调用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}}
发送消息
我们必须把信息发送到每一个本地IP。我们可以使用本地IP地址来获得前三个字节,并由此建立本地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) {}}
在本例中,它只将消息发送到从x.x.x.1到x.x.x.199的IP地址上,但理论上,我们可以从1发送到255。
现在,我们可以向活跃的本地设备发送信息。左下方的图片是一个物理的iOS设备,右边的是一个macOS桌面应用程序。虽它们有不同的本地IP地址,但你可以看到他们可以互相发送消息。
