앱에서 자기 자신의 ip주소를 얻어와야 할 때가 있는데..
음... 특히 내 경우는 hot spot 상태에서 폰의 local ip address하고 폰에 붙은 클라이언트들의 ip address를 읽어와야 할 때가 있어.
그래서 해봤음.
기본적인 아이디어는 이래.
- dart:io 패키지-> NetworkInterface class를 통해 hot spot용 네트워크 인터페이스가 생겼는지 확인하고 로컬 ip 주소를 가져왓!
- dart_ping 패키지를 사용해 2 ~ 255 까지 핑 쐇!
- 핑이 있는 ip 주소 업데이트!
참 쉽죠?
main을 보자! 👇
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:ithernet/screens/screen_main/screen_main.dart';
import 'package:ithernet/screens/screen_main/screen_main_binding.dart';
import 'package:dart_ping_ios/dart_ping_ios.dart';
void main() {
DartPingIOS.register();
runApp(
GetMaterialApp(
title: 'ithernet',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: "/",
getPages: [
GetPage(
name: "/",
page: () => const ScreenMain(),
binding: ScreenMainBinding(),
),
],
),
);
}
특별한 건 없지만 dart_ping을 ios에서 사용하기 위해서 앱 시작전 DartPingIOS.register()를 해줘야 한다는 점!
그리고 나머지는 get 관련된 것들...
난 get을 선호하니까!
이제 ScreenMain이랑 Controller를 봅시다
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'screen_main_controller.dart';
class ScreenMain extends GetView<ScreenMainController> {
const ScreenMain({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Hot Spot network information'),
),
body: SafeArea(
child: Center(
child: Obx(
() => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () async {
controller.ipAddr.value.isEmpty
? controller.getLocalIpAddress()
: controller.getClientIpAddress();
},
child: Text("Scan")),
Text("Network Information"),
Text("ip address"),
Text(controller.ipAddr.value.isEmpty
? "There is no network interface for hot spot."
: controller.ipAddr.value),
Text("Client's ip addresses")
] +
controller.clientIpAddress.value.map((e) => Text(e)).toList(),
),
),
),
),
);
}
}
진짜 뭐 별거 없다.
ScreenMain은 설명 패스~ 아래와 같은 화면 보이는 스크린이고~
Controller 파트인데
👇
여기서 눈 여겨 볼 건 NetworkInterface를 통해서 네트워크 인터페이스들을 가져오고
"bridge"로 시작하는 이름이 Hot spot 용 인터페이스라는 거!
그리고 ping을 쏴서 폰에 붙은 클라이언트들을 찾아낸다는거!
import 'package:get/get.dart';
import 'dart:io';
import 'package:dart_ping/dart_ping.dart';
//screenMainController
class ScreenMainController extends GetxController {
final ipAddr = ''.obs;
final clientIpAddress = Rx<List<String>>([]);
@override
void onInit() async {
ever(ipAddr, (value) async {
await getClientIpAddress();
});
ipAddr.value = await getLocalIpAddress();
super.onInit();
}
@override
void onClose() {
// TODO: implement onClose
super.onClose();
}
Future<String> getLocalIpAddress() async {
var interfaces = await NetworkInterface.list();
//iterate addresses only member main starts with "bridge"
for (var interface in interfaces) {
if (interface.name.startsWith("bridge")) {
for (var addr in interface.addresses) {
if (addr.type == InternetAddressType.IPv4 && !addr.isLoopback) {
ipAddr.value = addr.address;
}
}
}
}
return Future<String>.value(null);
}
//get client ip address from local ip address
//ping 2 to 255
Future<void> getClientIpAddress() async {
if (ipAddr.value == '') return;
var prefix = ipAddr.value.substring(0, ipAddr.value.lastIndexOf('.'));
for (int i = 2; i <= 255; i++) {
//send ping to each ip address
Ping(prefix + '.' + i.toString(), count: 1).stream.listen((event) {
if (event.summary?.received == 1) {
//if ping is received, add ip address to list
//if there is the same value in the list, do not add
if (clientIpAddress.value.contains(prefix + '.' + i.toString()))
return;
clientIpAddress.value.add(prefix + '.' + i.toString());
clientIpAddress.refresh();
}
});
}
}
}
이미 결과는 위 스샷에 있지 훗. 다시 보자면👇👇
맥북에서도 동일한 결과를 확인할 수 있어.
그런데 잠깐! 서브넷 마스크가 255.255.255.240이네 ㅋㅋㅋ
2~ 255까지 돌릴 필요도 없었구만!
172.20.10.2 ~ 172.20.10.15 까지만 돌려도 되겠어.
255개 핑 쏘는게 좀 부담스러웠는데 ㅎㅎ 굿굿!
그런데 응?
그런데 Network Interface에 subnet mask 정보가 없네?
ㅠㅠ 더 찾아봐야겠다.
아이폰은 255.255.255.240으로 고정인가?
흐음~~~~~~~
암튼 이런식으로 hotspot 사용할 때 local ip address하고 client ip address를 획득할 수 있다는거!
이거 가지고 뭐하냐고? ㅋㅋㅋㅋ 그건 천천히 생각해보자구 ㅋ
그럼 안녕! 아디오스!
👋👋👋👋👋👋