问题描述
我想从我的 iPhone 获取连接路由器的 IP 地址.我只能获取 iPhone 的 IP 地址.
I want to get the IP address of the connected router from my iPhone. I'm getting the IP address of my iPhone only.
有什么方法可以获得主机/路由器的 IP 地址吗?
Is there any way by which I can get the host/router IP address?
顺便说一句,我已经查看了以下链接,但没有解决方案:
BTW I already reviewed following links but no solutions there:
我正在尝试使用 XCode 12.4 在 Swift 5 中做到这一点
I'm trying to do it in Swift 5 with XCode 12.4
推荐答案
您可以使用 sysctl
从路由表中获取默认网关的 IP 地址,但首先您应该定义所需的结构和常量,因为 Darwin.net.route
或 不会暴露给 iOS SDK:
You can get IP address of your default gateway from the routing table using sysctl
but first you should define needed structures and constants because Darwin.net.route
or <route.h>
is not exposed to iOS SDK:
let RTAX_GATEWAY = 1
let RTAX_MAX = 8
public struct rt_metrics {
public var rmx_locks: UInt32 /* Kernel leaves these values alone */
public var rmx_mtu: UInt32 /* MTU for this path */
public var rmx_hopcount: UInt32 /* max hops expected */
public var rmx_expire: Int32 /* lifetime for route, e.g. redirect */
public var rmx_recvpipe: UInt32 /* inbound delay-bandwidth product */
public var rmx_sendpipe: UInt32 /* outbound delay-bandwidth product */
public var rmx_ssthresh: UInt32 /* outbound gateway buffer limit */
public var rmx_rtt: UInt32 /* estimated round trip time */
public var rmx_rttvar: UInt32 /* estimated rtt variance */
public var rmx_pksent: UInt32 /* packets sent using this route */
public var rmx_state: UInt32 /* route state */
public var rmx_filler: (UInt32, UInt32, UInt32) /* will be used for TCP's peer-MSS cache */
}
public struct rt_msghdr2 {
public var rtm_msglen: u_short /* to skip over non-understood messages */
public var rtm_version: u_char /* future binary compatibility */
public var rtm_type: u_char /* message type */
public var rtm_index: u_short /* index for associated ifp */
public var rtm_flags: Int32 /* flags, incl. kern & message, e.g. DONE */
public var rtm_addrs: Int32 /* bitmask identifying sockaddrs in msg */
public var rtm_refcnt: Int32 /* reference count */
public var rtm_parentflags: Int32 /* flags of the parent route */
public var rtm_reserved: Int32 /* reserved field set to 0 */
public var rtm_use: Int32 /* from rtentry */
public var rtm_inits: UInt32 /* which metrics we are initializing */
public var rtm_rmx: rt_metrics /* metrics themselves */
}
public func getDefaultGateway() -> String? {
var name: [Int32] = [
CTL_NET,
PF_ROUTE,
0,
0,
NET_RT_DUMP2,
0
]
let nameSize = u_int(name.count)
var bufferSize = 0
sysctl(&name, nameSize, nil, &bufferSize, nil, 0)
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
defer { buffer.deallocate() }
buffer.initialize(repeating: 0, count: bufferSize)
guard sysctl(&name, nameSize, buffer, &bufferSize, nil, 0) == 0 else { return nil }
// Routes
var rt = buffer
let end = rt.advanced(by: bufferSize)
while rt < end {
let msg = rt.withMemoryRebound(to: rt_msghdr2.self, capacity: 1) { $0.pointee }
// Addresses
var addr = rt.advanced(by: MemoryLayout<rt_msghdr2>.stride)
for i in 0..<RTAX_MAX {
if (msg.rtm_addrs & (1 << i)) != 0 && i == RTAX_GATEWAY {
let si = addr.withMemoryRebound(to: sockaddr_in.self, capacity: 1) { $0.pointee }
if si.sin_addr.s_addr == INADDR_ANY {
return "default"
}
else {
return String(cString: inet_ntoa(si.sin_addr), encoding: .ascii)
}
}
let sa = addr.withMemoryRebound(to: sockaddr.self, capacity: 1) { $0.pointee }
addr = addr.advanced(by: Int(sa.sa_len))
}
rt = rt.advanced(by: Int(msg.rtm_msglen))
}
return nil
}
// How to use
if let ip = getDefaultGateway() {
print(ip)
}
// Prints: 192.168.1.1
这篇关于如何在 Swift iOS 中获取路由器的 IP 地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!