[英]Get Network (Not device) IP address iOS swift
I have made some code for getting the Wi-Fi current SSID and device current IP but i need to get the Network IP Address so if my device's IP is 192.168.4.3 i Know it is connected to 192.168.4.1 Network but I need not to make this assumption in the code ... 我已经编写了一些代码来获取Wi-Fi当前的SSID和设备的当前IP,但是我需要获取网络IP地址,因此,如果我的设备的IP为192.168.4.3,我知道它已连接至192.168.4.1网络,但是我不需要在代码中做这个假设...
Get SSID: 获取SSID:
private func fetchSSIDInfo() -> String? {
var ssid: String?
if let interfaces = CNCopySupportedInterfaces() as NSArray? {
for interface in interfaces {
if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? {
ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
break
}
}
}
return ssid
}
Get Device's IP 获取设备的IP
static func getIPAddress()->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
}
¿¿Network IP address?? ??网络IP地址?
** Edit ** if I call ifa_netmask it returns the netmask which it 255.255.255.0 for a 192.168.4.2/24 IP **编辑**如果我调用ifa_netmask它将返回255.255.255.0的192.168.4.2/24 IP地址的网络掩码
It seems that you are looking for your external IP, while your local IP is 192.168.4.1. 似乎您在寻找外部IP,而本地IP为192.168.4.1。 Without the help of some external service, it is impossible ...
没有一些外部服务的帮助,这是不可能的...
UPDATE see rfc1533 rfc2131 for details, try in Playground :-) 更新请参见rfc1533 rfc2131了解详细信息,请在Playground中尝试:-)
import Foundation
func pack<T:FixedWidthInteger>(_ fi: T)->Data {
var nfi = fi
if 1 == 1.littleEndian {
nfi = fi.bigEndian
}
return withUnsafeBytes(of: nfi) { un -> Data in
var data = Data()
un.forEach({ (byte) in
data.append(byte)
})
return data
}
}
enum StringPack {
case ipv4, ipv6, mac
}
func pack(_ txt: String, type: StringPack)->Data {
var data = Data()
switch type {
case .ipv4:
txt.split(separator: ".", omittingEmptySubsequences: false).forEach { s in
data.append(UInt8(s) ?? 0)
}
while data.count < 4 { // padding with 0
data.append(0)
}
case .ipv6:
txt.split(separator: ":", omittingEmptySubsequences: false).forEach { (s) in
data.append(pack(UInt16(s, radix: 16) ?? 0))
}
while data.count < 8 { // padding with 0
data.append(0)
}
case .mac:
txt.split(separator: ":", omittingEmptySubsequences: false).forEach { s in
s
UInt8(s, radix:16)
data.append(UInt8(s, radix:16) ?? 0)
}
while data.count < 16 { // padding with 0
data.append(0)
}
}
return data
}
func dhcp_packet(
// all parameters have default value (https://www.ietf.org/rfc/rfc2131.txt) for client using wifi interface
op: UInt8 = 1, htype: UInt8 = 1, hlen: UInt8 = 6, hops: UInt8 = 0,
xid: UInt32 = UInt32.random(in: UInt32.min...UInt32.max),
secs: UInt16 = 0, flags: UInt16 = 0,
ciaddr: String = "...",
yiaddr: String = "...",
siaddr: String = "...",
giaddr: String = "...",
chaddr: String = ":::::",
sname: String = "",
file: String = ""
)->Data {
// data represents dhcp_packet
var data = Data()
// sd tuple represents predefined fixed size data
var sd:(Data, Int)
data.append(op)
data.append(htype)
data.append(hlen)
data.append(hops)
data.append(pack(xid))
data.append(pack(secs))
data.append(pack(flags))
data.append(pack(ciaddr, type: .ipv4))
data.append(pack(yiaddr, type: .ipv4))
data.append(pack(siaddr, type: .ipv4))
data.append(pack(giaddr, type: .ipv4))
data.append(pack(chaddr, type: .mac))
sd = (Data(count: 64), min(sname.utf8.count, 64))
sd.0.replaceSubrange(0..<sd.1, with: Data(sname.utf8)[0..<sd.1])
data.append(sd.0)
sd = (Data(count: 128), min(file.utf8.count, 128))
sd.0.replaceSubrange(0..<sd.1, with: Data(sname.utf8)[0..<sd.1])
data.append(sd.0)
return data
}
import Darwin
func getWiFiAddress() -> (ip4: String, mac: String, addr: sockaddr_in) {
var address : String = "..."
var mac: String = ":::::"
var success: Bool
var addr_in = sockaddr_in()
var ifaddr : UnsafeMutablePointer<ifaddrs>?
success = getifaddrs(&ifaddr) == 0
assert(success)
assert(ifaddr != nil)
let firstAddr = ifaddr!
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
let addrFamily = interface.ifa_addr.pointee.sa_family
let name = String(cString: interface.ifa_name)
if name == "en0" {
if addrFamily == UInt8(AF_INET) {
var addr = interface.ifa_addr.pointee
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
success = getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0
assert(success)
addr_in = withUnsafePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
$0.pointee
}
}
address = String(cString: hostname)
}
if addrFamily == UInt8(AF_LINK) {
interface.ifa_addr.withMemoryRebound(to: sockaddr_dl.self, capacity: 1) { (sdl) -> Void in
var hw = sdl.pointee.sdl_data
withUnsafeBytes(of: &hw, { (p) -> Void in
mac = p[Int(sdl.pointee.sdl_nlen)..<Int(sdl.pointee.sdl_alen + sdl.pointee.sdl_nlen)].map({ (u) -> String in
var s = String(u, radix:16)
if s.count < 2 {
s.append("0")
s = String(s.reversed())
}
return s
}).joined(separator: ":")
})
}
}
}
}
freeifaddrs(ifaddr)
return (address, mac, addr_in)
}
func sendBroadcast(data: Data, toPort: UInt16, waitForReplayOn: sockaddr_in)->Data {
var wifiInterface: UInt32
var fd: Int32
var success: Bool
var destAddr = sockaddr_in()
var response = Data()
wifiInterface = if_nametoindex("en0")
assert(wifiInterface != 0)
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
assert(fd >= 0)
var kOne = 1
success = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0
assert(success)
success = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0
assert(success)
success = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0
assert(success)
var wait = timeval(tv_sec: 0, tv_usec: 64000)
success = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &wait, socklen_t(MemoryLayout.size(ofValue: wait))) == 0
assert(success)
success = setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &wifiInterface, socklen_t(MemoryLayout.size(ofValue: wifiInterface))) == 0
assert(success)
var addr_in = waitForReplayOn
success = bindresvport(fd, &addr_in) == 0
assert(success)
destAddr.sin_family = sa_family_t(AF_INET)
destAddr.sin_len = __uint8_t(MemoryLayout.size(ofValue: destAddr))
destAddr.sin_addr.s_addr = INADDR_BROADCAST
destAddr.sin_port = in_port_t(toPort.bigEndian)
let bytesSent = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in
let destAddrSize = socklen_t(MemoryLayout.size(ofValue: destAddr))
return withUnsafePointer(to: &destAddr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
sendto(fd, bytes, data.count, 0, $0, destAddrSize)
}
}
}
if (bytesSent >= 0) {
print("DHCP packet with \(bytesSent) bytes broadcasted to UDP port \(toPort)")
var receiveBuffer = [UInt8](repeating: 0, count: 1024)
let bytes = recv(fd, &receiveBuffer, receiveBuffer.count, 0)
response.append(contentsOf: receiveBuffer[0..<bytes])
} else {
print("error", errno)
}
success = close(fd) == 0
assert(success)
return response
}
var en0info = getWiFiAddress()
var packet = dhcp_packet(/*ciaddr: en0info.ip4,*/ chaddr: en0info.mac)
let dhcp_MAGIC_COOKIE: [UInt8] = [0x63, 0x82, 0x53, 0x63]
// DHCP_OPTIONS [code, length, value]
let dhcp_DHCPINFORM : [UInt8] = [53, 1, 8]
// we request router(s) address (it is standart report, but ... :-)
// see https://www.ietf.org/rfc/rfc1533.txt
let dhcp_PARAMETER_REQUEST_LIST: [UInt8] = [55, 1, 3]
let dhcp_OPTIONS_END: UInt8 = 0xFF
packet.append(contentsOf: dhcp_MAGIC_COOKIE)
packet.append(contentsOf: dhcp_DHCPINFORM)
packet.append(contentsOf: dhcp_PARAMETER_REQUEST_LIST)
packet.append(dhcp_OPTIONS_END)
en0info.addr.sin_len = __uint8_t(MemoryLayout.size(ofValue: sockaddr_in()))
en0info.addr.sin_port = in_port_t(UInt16(68).bigEndian)
en0info.addr.sin_addr.s_addr = INADDR_ANY
var success = false
var attempt = 5
var response = Data()
repeat {
response = sendBroadcast(data: packet, toPort: 67, waitForReplayOn: en0info.addr)
// if succes is false, response is not for us, or invalid
success = response[1..<240] == packet[1..<240]
attempt -= 1
} while success == false && attempt > 0
if success == true {
success = false
var index = 240
let maxIndex = response.count
var option = (code: UInt8, length: UInt8, value: [UInt8])(0,0,[])
var options = [UInt8: [UInt8]]()
repeat {
option.code = response[index]
index += 1
if option.code == 0 {
continue
}
if option.code == 255 {
success = true
break
}
option.length = response[index]
index += 1
let nexti = index + Int(option.length)
if nexti <= maxIndex {
option.value = Array(response[index..<nexti])
options[option.code] = option.value
}
index = nexti
} while index < maxIndex
print(options, success ? "OK" : "incoplete")
} else {
print("DHCPINFORM failed")
}
On my environment it prints 在我的环境中打印
DHCP packet with 244 bytes broadcasted to UDP port 67
[3: [192, 168, 8, 1], 6: [192, 168, 8, 1, 192, 168, 8, 1], 53: [5], 54: [192, 168, 8, 1], 1: [255, 255, 255, 0]]
where: 哪里:
option 3 represents a list of the routers 选项3代表路由器列表
option 6 represents a list of DNS servers 选项6代表DNS服务器列表
option 53 means DHCP Message Type DHCPACK 选项53表示DHCP消息类型DHCPACK
option 54 means DHCP Server Identifier (where is this particular response from) 选项54表示DHCP服务器标识符(此特定响应来自何处)
option 1 represents Subnet Mask 选项1代表子网掩码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.