Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Flutter

[Flutter] Iphone Local ip address

방피터 2023. 3. 20. 22:21

앱에서 자기 자신의 ip주소를 얻어와야 할 때가 있는데..

음... 특히 내 경우는 hot spot 상태에서 폰의 local ip address하고 폰에 붙은 클라이언트들의 ip address를 읽어와야 할 때가 있어.

그래서 해봤음.

기본적인 아이디어는 이래.

  1. dart:io 패키지-> NetworkInterface class를 통해 hot spot용 네트워크 인터페이스가 생겼는지 확인하고 로컬 ip 주소를 가져왓!
  2. dart_ping 패키지를 사용해 2 ~ 255 까지 핑 쐇!
  3. 핑이 있는 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();
        }
      });
    }
  }
}

가장 마지막 네트워크 인터페이스 이름이 "bridge100"

이미 결과는 위 스샷에 있지 훗. 다시 보자면👇👇

결과 화면

맥북에서도 동일한 결과를 확인할 수 있어.

맥북과 동일하다!

그런데 잠깐! 서브넷 마스크가 255.255.255.240이네 ㅋㅋㅋ  

2~ 255까지 돌릴 필요도 없었구만!

172.20.10.2 ~ 172.20.10.15 까지만 돌려도 되겠어.

255개 핑 쏘는게 좀 부담스러웠는데 ㅎㅎ 굿굿!

그런데 응?

아무리 찾아도 subnet mask 정보는 없다 ㅠㅠ

그런데 Network Interface에 subnet mask 정보가 없네?

ㅠㅠ 더 찾아봐야겠다.

아이폰은 255.255.255.240으로 고정인가?

흐음~~~~~~~

암튼 이런식으로 hotspot 사용할 때 local ip address하고 client ip address를 획득할 수 있다는거!

이거 가지고 뭐하냐고? ㅋㅋㅋㅋ 그건 천천히 생각해보자구 ㅋ

그럼 안녕! 아디오스! 

👋👋👋👋👋👋

반응형