Swift - 장치의 WIFI IP 주소 가져오기
나는 스위프트에 있는 iOS 기기의 IP 주소를 얻어야 합니다.이것은 이것에 대한 다른 질문의 중복이 아닙니다!와이파이 IP 주소만 받으면 되는데, 와이파이 IP 주소가 없으면 제가 처리해야 합니다.스택 오버플로에 대한 몇 가지 질문이 있지만 IP 주소를 반환하는 기능만 있습니다.예: (IP 주소를 신속하게 가져오는 방법에서):
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
}
여기서 저는 모바일 인터넷 주소(내 생각에는)와 제가 필요로 하는 와이파이 주소라는 두 가지 값을 얻습니다.와이파이 IP 주소만 얻을 수 있는 다른 방법이 있나요?
여러 SO 스레드에 따르면(예: iOS 네트워킹 인터페이스 이름이 정확히 무엇을 의미합니까?) pdp_ip란 무엇입니까?ap란 무엇입니까?), iOS 기기의 WiFi 인터페이스는 항상 "en0"이라는 이름을 가집니다.
당신의 코드(이것은 내가 How to get Ip address in swift :)에서 대답한 것으로 보입니다. 모든 실행 중인 네트워크 인터페이스의 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의 많은 변경 사항에 코드를 적용하는 것 외에도, 이제 모든 인터페이스에서 반복하여 다음과 같은 새로운 일반화 기능을 사용할 수 있습니다.
추가하는 것을 잊지 마십시오.#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
}
와이파이 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 }
와이파이, 유선 및 셀룰러용 IP 주소를 얻으려면 - 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 }
guard let interface = ptr?.pointee else { return "" }
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>
브리징 헤더 생성 및 포함#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
}
내가 보기에 이 방법을 컨트롤러라고 부를 때는 다음과 같습니다.var arr : NSArray = self.getIFAddresses()
콘솔에서 다음과 같은 완벽한 응답을 받습니다.
IP :( "10.0.0.94" )
이 배열에서 원하는 곳 어디서나 액세스할 수 있습니다.도움이 되길 바랍니다.
스위프트 4.2UIDevice
강제로 랩을 풀지 않고 셀룰러 및 유선 IP 주소를 지원하는 확장 기능:
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()
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
}
약간 다른 접근 방식의 또 다른 솔루션은 IP를 얻기 위해 ping할 수 있는 무료 경량 서비스인 Ipify를 사용하는 것입니다.
Swift의 예는 다음과 같습니다.
let url = URL(string: "https://api.ipify.org")
do {
if let url = url {
let ipAddress = try String(contentsOf: url)
print("My public IP address is: " + ipAddress)
}
} catch let error {
print(error)
}
아래 코드를 사용하여 IP 주소를 가져올 수 있습니다.
참고 : WiFi가 다른 IP로 변경될 경우 새로운 IP 주소를 캡처할 수 있도록 도달 가능성을 사용하였습니다.
Podfile
파일pod 'ReachabilitySwift'
그리고 나서.install pod
AppDelegate.swift
파일import ReachabilitySwift
참고: ReachabilitySwift 모듈을 찾을 수 없다는 오류 메시지가 표시되면 이 모듈을 복사하여 붙여넣기만 하면 됩니다.효과가 있습니다!
didFinishLaunchingOptions
를 수행NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability) do{ try reachability.startNotifier() } catch { print("could not start reachability notifier") }
다음코아붙복사기여넣래에드▁in▁code▁below▁paste 코드 아래에 붙여넣기를 복사하세요.
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 }
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.
}
관찰자를 제거하려면 다음을 수행합니다.
reachability.stopNotifier() NSNotificationCenter.defaultCenter().removeObserver(self,name: ReachabilityChangedNotification,object: reachability)
스위프트 5 청소
위의 답변을 업데이트하여 강제로 포장을 풀고 SwiftLint 청소를 제거했습니다.
class func getIPAddress() -> String? {
var address: String?
var ifaddr: UnsafeMutablePointer<ifaddrs>?
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),
let cString = interface?.ifa_name,
String(cString: cString) == "en0",
let saLen = (interface?.ifa_addr.pointee.sa_len) {
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
let ifaAddr = interface?.ifa_addr
getnameinfo(ifaAddr,
socklen_t(saLen),
&hostname,
socklen_t(hostname.count),
nil,
socklen_t(0),
NI_NUMERICHOST)
address = String(cString: hostname)
}
}
freeifaddrs(ifaddr)
}
return address
}
이 클래스는 NWPathMonitor를 사용하여 장치 인터페이스를 모니터링합니다.인터페이스 상태 변경에 대해 알려주는 업데이트 처리기를 설정할 수 있습니다.ipv4 또는 ipv6를 추적하고 상태를 확인하려면 이 항목을 선택합니다.활성 인터페이스가 WiFi인지 확인하려면 interfaceType == .filename
용도:
let monitor = IPMonitor(ipType: .ipv4)
monitor.pathUpdateHandler = { status in
print("\(status.debugDescription)")
}
클래스:
import Foundation
import Network
class IPMonitor {
enum InterfaceType: String {
case cellular = "cellular"
case wifi = "wifi"
case wired = "wired"
case loopback = "loopback"
case other = "other"
case notFound = "not found"
}
enum IPType: String {
case ipv4 = "IPv4"
case ipv6 = "ipV6"
case unknown = "unknown"
}
struct Status {
var name = "unknown"
var interfaceType: InterfaceType = InterfaceType.notFound
var ip: [String] = []
var ipType: IPType = IPType.unknown
var debugDescription: String {
let result = "Interface: \(name)/\(interfaceType.rawValue), \(ipType.rawValue)\(ip.debugDescription)"
return result
}
}
private let monitor = NWPathMonitor()
private let queue = DispatchQueue(label: "ip_monitor_queue")
final var pathUpdateHandler: ((Status) -> Void)?
init(ipType: IPType) {
monitor.pathUpdateHandler = { path in
let name = self.getInterfaceName(path: path)
let type = self.getInterfaceType(path: path)
let ip = self.getIPAddresses(interfaceName: name, ipType: ipType)
let status = Status(name: name, interfaceType: type, ip: ip, ipType: ipType)
//print("\(status)")
self.pathUpdateHandler?(status)
}
monitor.start(queue: queue)
}
private func getInterfaceName(path: NWPath) -> String {
if let name = path.availableInterfaces.first?.name {
return name
}
return "unknown"
}
private func getInterfaceType(path: NWPath) -> InterfaceType {
if let type = path.availableInterfaces.first?.type {
switch type {
case NWInterface.InterfaceType.cellular:
return InterfaceType.cellular
case NWInterface.InterfaceType.wifi:
return InterfaceType.wifi
case NWInterface.InterfaceType.wiredEthernet:
return InterfaceType.wired
case NWInterface.InterfaceType.loopback:
return InterfaceType.loopback
default:
return InterfaceType.other
}
}
return InterfaceType.notFound
}
private func getIPAddresses(interfaceName: String, ipType: IPType)-> [String]{
var addresses: [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) && ipType == .ipv4)
|| (addrFamily == UInt8(AF_INET6) && ipType == .ipv6) {
let name = String(cString: (interface?.ifa_name)!)
if name == interfaceName {
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)
addresses.append(String(cString: hostname))
}
}
}
}
freeifaddrs(ifaddr)
return addresses
}
}
의 내선 .NWInterface.InterfaceType
위의 답변 중 일부를 기반으로 합니다.
import Network
extension NWInterface.InterfaceType {
var names : [String]? {
switch self {
case .wifi: return ["en0"]
case .wiredEthernet: return ["en2", "en3", "en4"]
case .cellular: return ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
default: return nil
}
}
func address(family: Int32) -> String?
{
guard let names = names else { return nil }
var address : String?
for name in names {
guard let nameAddress = self.address(family: family, name: name) else { continue }
address = nameAddress
break
}
return address
}
func address(family: Int32, name: String) -> String? {
var address: String?
// Get list of all interfaces on the local machine:
var ifaddr: UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0, let firstAddr = ifaddr else { return nil }
// For each interface ...
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(family)
{
// Check interface name:
if name == String(cString: interface.ifa_name) {
// 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
}
var ipv4 : String? { self.address(family: AF_INET) }
var ipv6 : String? { self.address(family: AF_INET6) }
}
용도:
: ipv4의 경우:NWInterface.InterfaceType.cellular.ipv4
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
}
여기에 있는 모든 답변은 유선 또는 셀룰러가 아닌 와이파이에 대한 IP 주소만 제공합니다.다음 스니펫은 wifi/wired/cellular 케이스에 사용할 수 있습니다.
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 및 IPV6 지원
UIDevice의 확장자로 만들고 UIDevice.current.get을 사용하여 호출합니다.IP 주소()
private struct Interfaces {
// INTERFACCIE SUPPORT
static let wifi = ["en0"]
static let cellular = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
static let supported = wifi + cellular
}
func getIPAdress() -> (String?,String?)? {
var ip4Adress: String?
var ip6Adress: String?
var hasAdress: UnsafeMutablePointer<ifaddrs>?
if getifaddrs(&hasAdress) == 0 {
var pointer = hasAdress
while pointer != nil {
defer { pointer = pointer?.pointee.ifa_next}
guard let interface = pointer?.pointee else {continue}
// SEARCH FOR IPV4 OR IPV6 IN THE INTERFACE OF THE NODE
// HERE I'M ALREADY LOOSING MY MIND
// PRIORITY FOR IPV4 THAN IPV6
if interface.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
guard let ip4 = processInterface(interface: interface) else {
continue
}
ip4Adress = ip4
}
if interface.ifa_addr.pointee.sa_family == UInt8(AF_INET6) {
guard let ip6 = processInterface(interface: interface) else {
continue
}
ip6Adress = ip6
}
}
freeifaddrs(hasAdress)
}
return (ip4Adress, ip6Adress)
}
func processInterface(interface: ifaddrs) -> String? {
var ipAdress: String = ""
guard
let interfaceName = interface.ifa_name else {return nil}
guard
let interfaceNameFormatted = String(cString: interfaceName, encoding: .utf8) else {return nil}
guard Interfaces.supported.contains(interfaceNameFormatted) else {return nil}
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
print(interfaceNameFormatted)
// CONVERT THE SOCKET ADRESS TO A CORRESPONDING HOST AND SERVICE
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 formattedIpAdress = String(cString: hostname, encoding: .utf8) else {return nil}
if !formattedIpAdress.isEmpty {
ipAdress = formattedIpAdress
}
return ipAdress
}
출력으로 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")
}
enum Network: String {
case wifi = "en0"
case cellular = "pdp_ip0"
// case en1 = "en1"
// case lo = "lo0"
}
// get ipv4 or ipv6 address
extension UIDevice {
func address(family: Int32, for network: Network) -> String? {
var address: String?
// Get list of all interfaces on the local machine:
var ifaddr: UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0, let firstAddr = ifaddr else { return nil }
// For each interface ...
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(family) {
// 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
}
func ipv4(for network: Network) -> String? {
self.address(family: AF_INET, for: network)
}
func ipv6(for network: Network) -> String? {
self.address(family: AF_INET6, for: network)
}
// get all addresses
func getIFAddresses() -> [String] {
var addresses = [String]()
// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return [] }
guard let firstAddr = ifaddr else { return [] }
// For each interface ...
for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let flags = Int32(ptr.pointee.ifa_flags)
let addr = ptr.pointee.ifa_addr.pointee
// 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](repeating: 0, count: Int(NI_MAXHOST))
if (getnameinfo(ptr.pointee.ifa_addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0) {
let address = String(cString: hostname)
addresses.append(address)
}
}
}
}
freeifaddrs(ifaddr)
return addresses
}
}
사용방법
// for wifi
let wifi = UIDevice.current.ipv4(for: .wifi) # ipv4
let wifi6 = UIDevice.current.ipv6(for: .wifi) # ipv6
// for cellular
let cellular = UIDevice.current.ipv4(for: .cellular) # ipv4
let cellular6 = UIDevice.current.ipv6(for: .cellular) # ipv6
Mac에서 Swift용 - Swift 4: 이러한 방식으로 WiFi(이더넷뿐만 아니라)에서도 IP를 확인할 수 있습니다.
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
}
소켓의 파일 설명자가 이미 있으므로 Swift 5.2용 솔루션입니다.
// Depending on your case get the socket's file descriptor
// the way you want
let socketFd = foo()
// Get the remote address for that file descriptor
var addr: sockaddr_storage = sockaddr_storage()
var addr_len: socklen_t = socklen_t(MemoryLayout.size(ofValue: addr))
var hostBuffer = [CChar](repeating: 0, count: Int(NI_MAXHOST))
// Make local copy to avoid: "Overlapping accesses to 'addr',
// but modification requires exclusive access; consider copying
// to a local variable"
let addrLen = addr.ss_len
withUnsafeMutablePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
if getpeername(socketFd, $0, &addr_len) != 0 { return }
getnameinfo($0, socklen_t(addrLen), &hostBuffer, socklen_t(hostBuffer.count), nil, 0, NI_NUMERICHOST)
}
}
let connectedHost = String(cString: hostBuffer, encoding: .utf8)
enum Network: String {
case wifi = "en0"
case cellular = "pdp_ip0"
case hotspot = "bridge100"
}
핫스팟을 사용하면 IP를 얻습니다.
언급URL : https://stackoverflow.com/questions/30748480/swift-get-devices-wifi-ip-address
'IT' 카테고리의 다른 글
이 스팬을 디브의 오른쪽에 맞추는 방법은 무엇입니까? (0) | 2023.08.31 |
---|---|
설치된 웹 팩 버전 확인 방법 (0) | 2023.08.31 |
mariadb를 사용하도록 MAMP 구성 (0) | 2023.08.31 |
인라인 블록 DIV를 컨테이너 요소의 맨 위에 정렬 (0) | 2023.08.31 |
유니파이드 diff 파일에서 문자별 차이를 시각화하려면 어떻게 해야 합니까? (0) | 2023.08.26 |