Swift实现UDP广播时如何将sockaddr_in转换为sockaddr?
问题解决方法
在Swift中,sockaddr_in 和 sockaddr 是C语言定义的内存布局兼容的结构体,不需要手动构造sockaddr实例,只需要通过内存指针绑定的方式将sockaddr_in的指针转为sockaddr类型指针传入sendto即可,完全对应Objective-C代码里的(struct sockaddr*)&broadcastAddr强制转换逻辑。
同时你现有的Swift代码还有几处需要修正的问题:
sockaddr_in不需要声明为隐式解包可选类型,直接初始化实例即可- 端口号需要调用
htons()转为网络字节序(大端),和原有OC代码逻辑保持一致 - 地址字符串转UTF8 C字符串不需要自定义转换方法,直接使用Swift内置的
withCString方法更安全 - 新增
defer语句统一管理socket关闭,避免多个返回分支遗漏关闭操作
修正后的完整代码
func send(_ address: String) { let socketSD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) guard socketSD > 0 else { print("Error: Could not open socket.") return } // 无论函数如何返回都会自动关闭socket defer { close(socketSD) } // 开启广播权限 var broadcastEnable = 1 let retSetsockopt = setsockopt(socketSD, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, socklen_t(MemoryLayout.size(ofValue: broadcastEnable))) guard retSetsockopt == 0 else { print("Error: Could not set socket to broadcast mode") return } // 初始化目标地址结构体 var broadcastAddr = sockaddr_in() memset(&broadcastAddr, 0, MemoryLayout<sockaddr_in>.size) broadcastAddr.sin_family = sa_family_t(AF_INET) broadcastAddr.sin_port = htons(2425) // 转为网络字节序 // 转换IP地址格式 address.withCString { broadCast in inet_pton(AF_INET, broadCast, &broadcastAddr.sin_addr) } // 发送广播消息 let request = "message" let sendRet = request.withCString { requestPtr in withUnsafeBytes(of: &broadcastAddr) { addrBuf in sendto( socketSD, requestPtr, strlen(requestPtr), 0, addrBuf.baseAddress?.assumingMemoryBound(to: sockaddr.self), socklen_t(MemoryLayout<sockaddr_in>.stride) ) } } guard sendRet >= 0 else { print("Error: Could not send broadcast.") return } }
内容的提问来源于stack exchange,提问作者Vin
相关产品推荐
相关产品推荐

