gpt4 book ai didi

sockets - 如何快速将 sockaddr 转换为 sockaddr_in

转载 作者:行者123 更新时间:2023-12-03 11:51:44 27 4
gpt4 key购买 nike

var sa_tab:[sockaddr?] = [sockaddr](repeating: sockaddr(), count: Int(RTAX_MAX))
let addr:sockaddr = sa_tab[Int(RTAX_DST)]!
let addr_in:sockaddr_in = unsafeBitCast(addr.self, to: UnsafeMutablePointer<sockaddr_in>.self).pointee

我在第三行崩溃, 不能在不同大小的类型之间进行 unsafeBitCast

这是完整的方法。
func ROUNDUP(a:Int) -> Int{
if (a) > 0 {
return (1 + (((a) - 1) | (MemoryLayout<CLong>.size - 1)))
}
else{

return MemoryLayout<CLong>.size
}
}

class func defaultGatewayAddress() -> Int{

var addressIntValue:UInt32 = 0
var mib:[Int32] = [CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY]
let l = UnsafeMutablePointer<Int>.allocate(capacity: MemoryLayout<Int>.size)
var buf: UnsafeMutablePointer<CChar>?
var p: UnsafeMutablePointer<CChar>?
var rt: UnsafeMutablePointer<rt_msghdr>?
var sa:UnsafeMutablePointer<sockaddr>?
var sa_tab:[sockaddr?] = [sockaddr](repeating: sockaddr(), count: Int(RTAX_MAX))
var _:Int
var r:Int = -1

if(sysctl(&mib, u_int(mib.count), nil, l, nil, 0) < 0) {
return -1;
}
print(Int8.max)
print(Int8.min)
if(l.pointee > 0) {

buf = UnsafeMutablePointer<CChar>.allocate(capacity: l.pointee)

if(sysctl(&mib, u_int(mib.count), buf, l, nil, 0) < 0) {
return -1;
}


p = buf
let maxBuf = buf!.advanced(by: l.pointee)

while (p! < maxBuf) {

rt = p!.withMemoryRebound(to: rt_msghdr.self, capacity: 1, {$0})
sa = rt!.advanced(by: 1).withMemoryRebound(to: sockaddr.self, capacity: 1, {$0})

for i in 0..<RTAX_MAX {
if (rt!.pointee.rtm_addrs & (1 << i)) == 1{
print("insert \(sa!.pointee) at \(i)")
sa_tab.insert(sa!.pointee, at: Int(i))
sa = sa!.advanced(by: ROUNDUP(a: Int(sa!.pointee.sa_len)))
}
else{
sa_tab.insert(nil, at: Int(i))
}
if ((rt!.pointee.rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) &&
(sa_tab[Int(RTAX_DST)]?.sa_family == sa_family_t(AF_INET)) &&
(sa_tab[Int(RTAX_GATEWAY)]?.sa_family == sa_family_t(AF_INET)){

var addr:sockaddr = sa_tab[Int(RTAX_DST)]!

let addr_in:sockaddr_in = withUnsafePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
$0.pointee
}
}

if addr_in.sin_addr.s_addr == 0 {
var buffer = [CChar](repeating: CChar(0), count: Int(IFNAMSIZ) + 1)
let result = if_indextoname(UInt32((rt?.pointee.rtm_index)!), &buffer)
var char = "en0".cString(using: .utf8)
#if arch(i386) || arch(x86_64)
// This is a Simulator not an idevice
char = "en1".cString(using: .utf8)
#endif

if(strcmp(result, char) == 0){
r = 0
var gatewayAddr:sockaddr = sa_tab[Int(RTAX_GATEWAY)]!

let gatewayAddr_in:sockaddr_in = withUnsafePointer(to: &gatewayAddr) {
$0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
$0.pointee
}
}
addressIntValue = gatewayAddr_in.sin_addr.s_addr
}
}


}
}

p = p?.advanced(by: Int((rt?.pointee.rtm_msglen)!))

}

buf!.deallocate(capacity: l.pointee)

let gatewayLongAddress:UInt32 = addressIntValue

print("gatewayLongAddress: \(gatewayLongAddress)")

let gatewayIPAddress = String(format:"%d.%d.%d.%d", (gatewayLongAddress & 0xFF),
((gatewayLongAddress >> 8) & 0xFF),
((gatewayLongAddress >> 16) & 0xFF),
((gatewayLongAddress >> 24) & 0xFF))

print("gatewayIPAddress: \(gatewayIPAddress)")

}

return Int(addressIntValue)
}

最佳答案

您必须采取addr的地址(这需要addr作为变量),使用 withMemoryRebound()
暂时将其重新绑定(bind)到 sockaddr_in指针,然后可以
被取消引用:

var addr: sockaddr = ...
let addr_in = withUnsafePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
$0.pointee
}
}

您的 defaultGatewayAddress() 中存在一些问题方法:
  • sa = sa!.advanced(by: ROUNDUP(a: Int(sa!.pointee.sa_len)))预付款sa经过sa_len乘以 sockaddr 的大小,这不是你想要的。
  • 测试if ((rt!.pointee.rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))必须在 for i in 0..<RTAX_MAX 之后完成环形。
  • sa_tab.insert(sa!.pointee, at: Int(i))您将新元素插入
    数组而不是替换它们。

  • 另请注意
    rt = p!.withMemoryRebound(to: rt_msghdr.self, capacity: 1, {$0})

    可能在这里工作,但它通常不安全: $0指针仅适用于
    闭包的执行,绝不能传递给外部。

    这是您的代码的工作版本。它本质上是一个翻译
    How can I determine the default gateway on iPhone?
    到 Swift(它又似乎建立在 https://github.com/getlantern/libnatpmp/blob/master/getgateway.c 之上)。

    我还对其进行了一些简化和修改,以避免所有强制展开。
    func defaultGatewayAddress() -> in_addr? {

    var defaultGateway: in_addr?

    var mib:[Int32] = [CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY]
    var len = 0
    if sysctl(&mib, u_int(mib.count), nil, &len, nil, 0) < 0 {
    return nil
    }
    let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: len)
    defer {
    buffer.deallocate(capacity: len)
    }
    if sysctl(&mib, u_int(mib.count), buffer, &len, nil, 0) < 0 {
    return nil
    }

    var sa_tab = [UnsafePointer<sockaddr>?](repeating: nil, count: Int(RTAX_MAX))

    var ptr = buffer
    while ptr < buffer + len {
    ptr.withMemoryRebound(to: rt_msghdr.self, capacity: 1) { rt in
    var sa = UnsafeMutableRawPointer(rt + 1).assumingMemoryBound(to: sockaddr.self)
    for i in 0..<RTAX_MAX {
    if rt.pointee.rtm_addrs & (1 << i) != 0 {
    sa_tab[Int(i)] = UnsafePointer(sa)
    sa = (UnsafeMutableRawPointer(sa) + Int(sa.pointee.sa_len)).assumingMemoryBound(to: sockaddr.self)
    } else {
    sa_tab[Int(i)] = nil
    }
    }

    if let dst = sa_tab[Int(RTAX_DST)],
    dst.pointee.sa_family == sa_family_t(AF_INET),
    let gateway = sa_tab[Int(RTAX_GATEWAY)],
    gateway.pointee.sa_family == sa_family_t(AF_INET)
    {
    dst.withMemoryRebound(to: sockaddr_in.self, capacity: 1) { addr in
    if addr.pointee.sin_addr.s_addr == 0 {

    var name = [CChar](repeating: CChar(0), count: Int(IFNAMSIZ) + 1)
    if_indextoname(UInt32((rt.pointee.rtm_index)), &name)
    if String(cString: name) == "en0" {
    defaultGateway = gateway.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
    $0.pointee.sin_addr
    }
    }
    }
    }

    }
    ptr += Int(rt.pointee.rtm_msglen)
    }
    }

    return defaultGateway
    }

    关于sockets - 如何快速将 sockaddr 转换为 sockaddr_in,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44745209/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com