【问题标题】:How to get sockaddr from sockaddr_in in Swift?如何在 Swift 中从 sockaddr_in 获取 sockaddr?
【发布时间】:2021-12-12 07:31:43
【问题描述】:

您好,这是我成功发送广播消息的目标代码,

- (void)send: (NSString *)address
    {
        int socketSD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (socketSD <= 0) {
            NSLog(@"Error: Could not open socket.");
            return;
        }
        
        // set socket options enable broadcast
        int broadcastEnable = 1;
        int ret = setsockopt(socketSD, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
        if (ret) {
            NSLog(@"Error: Could not open set socket to broadcast mode");
            close(socketSD);
            return;
        }
        
        // Configure the port and ip we want to send to
        struct sockaddr_in broadcastAddr;
        memset(&broadcastAddr, 0, sizeof(broadcastAddr));
        broadcastAddr.sin_family = AF_INET;
        
        const char *broadCast = [address UTF8String];
        
        inet_pton(AF_INET, broadCast, &broadcastAddr.sin_addr);
        
        broadcastAddr.sin_port = htons(2425);
        
        char *request = "message";
        ret = sendto(socketSD, request, strlen(request), 0, (struct sockaddr*)&broadcastAddr, sizeof(broadcastAddr));
       
        if (ret < 0) {
            NSLog(@"Error: Could not open send broadcast.");
            close(socketSD);
            return;
        } 
        
        close(socketSD); 
    }

我尝试将此代码转换为 swift,但我不知道如何将 sockaddr_in 转换为 sockaddr。这是我尝试过的快速代码,

func send(_ address: String) {
        let socketSD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)
        if socketSD <= 0 {
            print("Error: Could not open socket.")
            return
        }

        // set socket options enable broadcast
        var broadcastEnable = 1
       
        var ret = setsockopt(socketSD, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, socklen_t(MemoryLayout.size(ofValue: broadcastEnable)))
        
        if ret != 0 {
            print("Error: Could not open set socket to broadcast mode")
            close(socketSD)
            return
        }
        
        var broadcastAddr: sockaddr_in!
        
        memset(&broadcastAddr, 0, MemoryLayout.size(ofValue: broadcastAddr))
        
        if broadcastAddr == nil{
            
            return
        }
        
        broadcastAddr.sin_family = sa_family_t(AF_INET)

        let broadCast: UnsafeMutablePointer<Int8>? = address.toUnsafeMutablePointer()

        inet_pton(AF_INET, broadCast, &broadcastAddr.sin_addr)

        broadcastAddr.sin_port = in_port_t(2425)
    
        let request = ("message" as NSString).utf8String
         
        
        var unsafePointerAddress: sockaddr = // I am not sure  how to get sockaddr from `broadcastAddr` 
        
        ret =  Int32(
            
            sendto(socketSD, request!, strlen(request!), 0, &unsafePointerAddress, socklen_t(MemoryLayout.size(ofValue: broadcastAddr)))
        )

        if ret < 0 {
            print("Error: Could not open send broadcast.")
            close(socketSD)
            return
        }

        close(socketSD)
    }

请帮助我。谢谢。

【问题讨论】:

    标签: swift cocoa swift5


    【解决方案1】:

    我根据您的开头将代码翻译为:

    func send(_ address: String) {
        let socketSD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)
        guard socketSD > 0 else { print("Error: Could not open socket."); return }
        defer { close(socketSD) }
    
        // set socket options enable broadcast
        var broadcastEnable = 1
        let ret = setsockopt(socketSD, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, socklen_t(MemoryLayout.size(ofValue: broadcastEnable)))
        guard ret == 0 else { print("Error: Could not open set socket to broadcast mode"); return }
    
        var broadcastAddr = sockaddr_in(sin_len: 0,
                                        sin_family: sa_family_t(AF_INET),
                                        sin_port: in_port_t(UInt16(1314).bigEndian),
                                        sin_addr: in_addr(s_addr: 0),
                                        sin_zero: (0,0,0,0,0,0,0,0))
        let broadcastAddrSize = MemoryLayout.size(ofValue: broadcastAddr)
    
        address.withCString {
            address in
            inet_pton(AF_INET, address, &broadcastAddr.sin_addr)
        }
    
        let result = withUnsafePointer(to: &broadcastAddr) {
            return $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { aSockaddr in
                return "message".withCString { message in
                    return sendto(socketSD, message, strlen(message), 0, aSockaddr, socklen_t(broadcastAddrSize))
    
                }
            }
        }
    
        print(result)
        if result < 0 {
            print("Error: Could not open send broadcast. \(result)")
        }
    }
    

    如果我运行它,它不会崩溃并返回肯定的结果,但我不知道它是否正常工作。

    【讨论】:

    • 感谢您的回答。但它不起作用。我收到错误Could not open send broadcast. -1nc -luk 1314 是收听广播消息的终端命令。使用ifconfig可以得到broadcast的IP地址。
    • Swift 版本 Objective-C 版本都给了我相同的结果 对 sendto 的调用失败并返回 -1 并留下 errno 值为 1 (域错误)。你知道 Objective-C 的愿景是否奏效了吗?
    • 是的,您的解决方案运行良好。问题是我们忘记检查Xcode中App Sandbox的传出连接Signing and Capabilities.谢谢你的回答。
    猜你喜欢
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 2013-09-07
    • 2010-12-21
    相关资源
    最近更新 更多