development

Swift-장치의 WIFI IP 주소 가져 오기

big-blog 2020. 11. 26. 19:05
반응형

Swift-장치의 WIFI IP 주소 가져 오기


Swift에서 iOS 기기의 IP 주소를 얻어야합니다. 이것은 이것에 대한 다른 질문과 중복되지 않습니다! WiFi IP 주소가없는 경우 WiFi IP 주소 만 가져 오면됩니다. 처리해야합니다. Stack Overflow에 대한 몇 가지 질문이 있지만 ip 주소를 반환하는 함수 만 있습니다. 예를 들어 ( How to get Ip address in swift ) :

func getIFAddresses() -> [String] {
    var addresses = [String]()

    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
    if getifaddrs(&ifaddr) == 0 {

        // For each interface ...
        for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) {
            let flags = Int32(ptr.memory.ifa_flags)
            var addr = ptr.memory.ifa_addr.memory

            // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
            if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {

                    // Convert interface address to a human readable string:
                    var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                    if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
                        nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                            if let address = String.fromCString(hostname) {
                                addresses.append(address)
                            }
                    }
                }
            }
        }
        freeifaddrs(ifaddr)
    }

    return addresses
}

여기서는 모바일 인터넷의 주소 (제 생각에)와 필요한 WiFi 주소의 두 가지 값을 얻습니다. WiFi IP 주소 만 얻을 수있는 다른 방법이 있습니까?


여러 SO 스레드 (예 : 정확히 iOS 네트워킹 인터페이스 이름을 의미하는 것은 무엇입니까? pdp_ip는 무엇입니까? ap는 무엇입니까? )에 따르면 iOS 장치의 WiFi 인터페이스 이름은 항상 "en0"입니다.

귀하의 코드 (내가 Ip 주소를 신속하게 얻는 방법에서 대답 한 것 같습니다 .)은 실행중인 모든 네트워크 인터페이스 의 IP 주소 목록을 검색합니다 . "en0"인터페이스의 IP 주소 만 반환하도록 쉽게 수정할 수 있으며 실제로 그 스레드에서 원래 답변 한 것입니다 (그리고 이것은 프로그래밍 방식으로 iphone의 IP 주소를 얻는 방법 에 대한 답변의 신속한 번역 일뿐입니다. ) :

// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
    var address : String?

    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
    if getifaddrs(&ifaddr) == 0 {

        // For each interface ...
        var ptr = ifaddr
        while ptr != nil {
            defer { ptr = ptr.memory.ifa_next }

            let interface = ptr.memory

            // Check for IPv4 or IPv6 interface:
            let addrFamily = interface.ifa_addr.memory.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                // Check interface name:
                if let name = String.fromCString(interface.ifa_name) where name == "en0" {

                    // Convert interface address to a human readable string:
                    var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                    getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.memory.sa_len),
                                &hostname, socklen_t(hostname.count),
                                nil, socklen_t(0), NI_NUMERICHOST)
                    address = String.fromCString(hostname)
                }
            }
        }
        freeifaddrs(ifaddr)
    }

    return address
}

용법:

if let addr = getWiFiAddress() {
    print(addr)
} else {
    print("No WiFi address")
}

Swift 3 업데이트 : Swift 3많은 변경 사항에 대한 코드를 채택하는 것 외에도 모든 인터페이스를 반복하면 이제 새로운 일반화 된 sequence()함수를 사용할 수 있습니다 .

NOT 추가하는 것을 잊지 #include <ifaddrs.h>당신의 브리지 헤더

// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
    var address : String?

    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }

    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee

        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if  name == "en0" {

                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)

    return address
}

WIFI IP보다 더 많은 것을 찾고 계신 분들은이 코드를 약간 수정할 수 있습니다.

func getAddress(for network: Network) -> String? {
    var address: String?

    // Get list of all interfaces on the local machine:
    var ifaddr: UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }

    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee

        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if name == network.rawValue {

                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)

    return address
}
enum Network: String {
    case wifi = "en0"
    case cellular = "pdp_ip0"
    //... case ipv4 = "ipv4"
    //... case ipv6 = "ipv6"
}

그런 다음 셀룰러 IP에도 액세스 할 수 있습니다.

guard let wifiIp = getAddress(for: .wifi) else { return }

&

guard let cellularIp = getAddress(for: .cellular) else { return }


브리징 헤더를 만들고 포함 #include <ifaddrs.h>합니다.

그런 다음이 방법을 작성하십시오.

func getIFAddresses() -> [String] {
var addresses = [String]()

// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
if getifaddrs(&ifaddr) == 0 {

    // For each interface ...
    for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) {
        let flags = Int32(ptr.memory.ifa_flags)
        var addr = ptr.memory.ifa_addr.memory

        // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
        if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
            if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {

                // Convert interface address to a human readable string:
                var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
                    nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                        if let address = String.fromCString(hostname) {
                            addresses.append(address)
                        }
                }
            }
        }
    }
    freeifaddrs(ifaddr)
}

  return addresses
}

내 viewController 에서이 메서드를 호출하면 var arr : NSArray = self.getIFAddresses()내 콘솔에서 완벽한 응답을 얻는 것처럼

IP :( "10.0.0.94")

이 배열에서 원하는 곳에 액세스 할 수 있습니다. 도움이되기를 바랍니다.


Swift 4-장치의 IP 주소 가져 오기 :

#include<ifaddrs.h>브리징 헤더를 추가 하십시오.

이것은 IP 주소를 얻는 데 필요한 프레임 워크입니다.

class func getIPAddress() -> String? {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }

                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                    if let name: String = String(cString: (interface?.ifa_name)!), name == "en0" {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        address = String(cString: hostname)
                    }
                }
            }
            freeifaddrs(ifaddr)
        }
        return address
}

UIDevice강제 풀림을 방지하고 셀룰러 및 유선 IP 주소를 지원하는 Swift 4.2 확장 :

import UIKit

extension UIDevice {

    private struct InterfaceNames {
        static let wifi = ["en0"]
        static let wired = ["en2", "en3", "en4"]
        static let cellular = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
        static let supported = wifi + wired + cellular
    }

    func ipAddress() -> String? {
        var ipAddress: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>?

        if getifaddrs(&ifaddr) == 0 {
            var pointer = ifaddr

            while pointer != nil {
                defer { pointer = pointer?.pointee.ifa_next }

                guard
                    let interface = pointer?.pointee,
                    interface.ifa_addr.pointee.sa_family == UInt8(AF_INET) || interface.ifa_addr.pointee.sa_family == UInt8(AF_INET6),
                    let interfaceName = interface.ifa_name,
                    let interfaceNameFormatted = String(cString: interfaceName, encoding: .utf8),
                    InterfaceNames.supported.contains(interfaceNameFormatted)
                    else { continue }

                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))

                getnameinfo(interface.ifa_addr,
                            socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname,
                            socklen_t(hostname.count),
                            nil,
                            socklen_t(0),
                            NI_NUMERICHOST)

                guard
                    let formattedIpAddress = String(cString: hostname, encoding: .utf8),
                    !formattedIpAddress.isEmpty
                    else { continue }

                ipAddress = formattedIpAddress
                break
            }

            freeifaddrs(ifaddr)
        }

        return ipAddress
    }

}

용법:

UIDevice.current.ipAddress()

Wi-Fi, 유선 및 셀룰러에 대한 IPAddress를 얻으려면 (swift 5)

func getIPAddress() -> String {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }

                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                    // wifi = ["en0"]
                    // wired = ["en2", "en3", "en4"]
                    // cellular = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]

                    let name: String = String(cString: (interface!.ifa_name))
                    if  name == "en0" || name == "en2" || name == "en3" || name == "en4" || name == "pdp_ip0" || name == "pdp_ip1" || name == "pdp_ip2" || name == "pdp_ip3" {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        address = String(cString: hostname)
                    }
                }
            }
            freeifaddrs(ifaddr)
        }
        return address ?? ""
    }

사용하는 방법

let strIPAddress : String = self.getIPAddress()
print("IPAddress :: \(strIPAddress)")

참고 : 프로젝트의 Bridging-Header 파일에 아래에 추가하십시오.

#include<ifaddrs.h>

아래 코드를 사용하여 IP 주소를 가져올 수 있습니다.

참고 : WiFi가 다른 IP 주소로 변경 될 경우 새 IP 주소를 캡처하도록 연결성을 사용했습니다.

  1. 에서 Podfile파일

    pod 'ReachabilitySwift' 그리고 install pod

  2. 에서 AppDelegate.swift파일import ReachabilitySwift

    참고 : ReachabilitySwift 모듈을 찾을 수 없다는 오류가 표시되면 간단히 복사하여 붙여 넣으십시오. 효과가있다!

  3. didFinishLaunchingOptions 함수

    NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability)
    
    do{
        try reachability.startNotifier()
    }
    catch {
        print("could not start reachability notifier")
    } 
    
  4. 그런 다음 AppDelegate파일의 코드 아래에 붙여 넣으십시오.

    func reachabilityChanged(note: NSNotification) {
    
        let reachability = note.object as! Reachability
    
        if reachability.isReachable {
            if reachability.isReachableViaWiFi {
                print("Reachable via WiFi")
            } else {
                print("Reachable via Cellular")
            }
    
            setIPAddress()
        } else {
            ipAddress = "" // No IP captures
            print("Network not reachable")
        }
    }
    
    func setIPAddress() {
        if let addr = self.getWiFiAddress() {
            print("ipAddress : \(addr)")
            ipAddress = addr
        } else {
            ipAddress = "" // No IP captures
            print("No WiFi address")
        }
    }
    
    // Return IP address of WiFi interface (en0) as a String, or `nil`
    func getWiFiAddress() -> String? {
        var address : String?
    
        // Get list of all interfaces on the local machine:
        var ifaddr : UnsafeMutablePointer<ifaddrs>?
        guard getifaddrs(&ifaddr) == 0 else { return nil }
        guard let firstAddr = ifaddr else { return nil }
    
        // For each interface ...
        for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
            let interface = ifptr.pointee
    
            // Check for IPv4 or IPv6 interface:
            let addrFamily = interface.ifa_addr.pointee.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
    
                // Check interface name:
                let name = String(cString: interface.ifa_name)
                if  name == "en0" {
    
                    // Convert interface address to a human readable string:
                    var addr = interface.ifa_addr.pointee
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                                &hostname, socklen_t(hostname.count),
                                nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostname)
                }
            }
        }
        freeifaddrs(ifaddr)
    
        return address
    }
    
  5. Bridging-Header 파일에 추가 #include<ifaddrs.h>

    이 파일이없는 경우 만들 수 있습니다. 이 링크를 확인하십시오.

6.

func applicationWillEnterForeground(_ application: UIApplication) {
        // Post notification
        NotificationCenter.default.post(name: ReachabilityChangedNotification, object: reachability)
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
  1. 관찰자를 제거하려면 다음을 수행하십시오.

    reachability.stopNotifier()  
    
    NSNotificationCenter.defaultCenter().removeObserver(self,name: ReachabilityChangedNotification,object: reachability)
    

func getIPAddress() -> String {
    var address: String = "error"

    var interfaces: ifaddrs? = nil

    var temp_addr: ifaddrs? = nil
    var success: Int = 0
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(interfaces)
    if success == 0 {
        // Loop through linked list of interfaces
        temp_addr = interfaces
        while temp_addr != nil {
            if temp_addr?.ifa_addr?.sa_family == AF_INET {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if (String(utf8String: temp_addr?.ifa_name) == "en0") {
                    // Get NSString from C String
                    address = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                }
            }
            temp_addr = temp_addr?.ifa_next
        }
    }
        // Free memory
    freeifaddrs(interfaces)
    return address
}

여기의 모든 답변은 유선 또는 셀룰러가 아닌 Wi-Fi에 대한 IP 주소 만 제공합니다. 다음 스 니펫은 Wi-Fi / 유선 / 휴대폰 케이스에 사용할 수 있습니다.

func getIPAddressForCellOrWireless()-> String? {

    let WIFI_IF : [String] = ["en0"]
    let KNOWN_WIRED_IFS : [String] = ["en2", "en3", "en4"]
    let KNOWN_CELL_IFS : [String] = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]

    var addresses : [String : String] = ["wireless":"",
                                         "wired":"",
                                         "cell":""]

    var address: String?
    var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
    if getifaddrs(&ifaddr) == 0 {

        var ptr = ifaddr
        while ptr != nil {
            defer { ptr = ptr?.pointee.ifa_next } // memory has been renamed to pointee in swift 3 so changed memory to pointee

            let interface = ptr?.pointee
            let addrFamily = interface?.ifa_addr.pointee.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                if let name: String = String(cString: (interface?.ifa_name)!), (WIFI_IF.contains(name) || KNOWN_WIRED_IFS.contains(name) || KNOWN_CELL_IFS.contains(name)) {

                    // String.fromCString() is deprecated in Swift 3. So use the following code inorder to get the exact IP Address.
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostname)
                    if WIFI_IF.contains(name){
                        addresses["wireless"] =  address
                    }else if KNOWN_WIRED_IFS.contains(name){
                        addresses["wired"] =  address
                    }else if KNOWN_CELL_IFS.contains(name){
                        addresses["cell"] =  address
                    }
                }

            }
        }
    }
    freeifaddrs(ifaddr)

    var ipAddressString : String?
    let wirelessString = addresses["wireless"]
    let wiredString = addresses["wired"]
    let cellString = addresses["cell"]
    if let wirelessString = wirelessString, wirelessString.count > 0{
        ipAddressString = wirelessString
    }else if let wiredString = wiredString, wiredString.count > 0{
        ipAddressString = wiredString
    }else if let cellString = cellString, cellString.count > 0{
        ipAddressString = cellString
    }
    return ipAddressString
}

출력으로 IPv4 응답 만 원하는 경우 Martin R의 솔루션을 수정하십시오.

 func getWiFiAddress() -> String? {
    var address : String?

    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }

    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee

        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        //if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {  // **ipv6 committed
        if addrFamily == UInt8(AF_INET){

            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if  name == "en0" {

                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)

    return address
}

용법:

if let addr = getWiFiAddress() {
   print(addr)
} else {
   print("No WiFi address")
}

For Swift on Mac - Swift 4 : This way you can also find out the ip from the Wifi (not only Ethernet)

func getWiFiAddress() -> String? {
    var address : String?

    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }

    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee

        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if  name == "en0" {

                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            } else if name == "en1" {
                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(1), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)

    return address
}

참고URL : https://stackoverflow.com/questions/30748480/swift-get-devices-wifi-ip-address

반응형