我一直在尝试创建与本地套接字文件的连接,但是errno总是返回-1
var socketPath = "/path/to/socket"
let sockDesc = socket(AF_LOCAL, SOCK_STREAM, 0)
var address = sockaddr_un()
address.sun_family = UInt8(AF_LOCAL)
address.sun_len = UInt8(bitPattern:Int8(MemoryLayout<sockaddr_un>.size))
let dataPtr = UnsafeMutablePointer<Int8>(&address.sun_path.0)
strncpy(dataPtr, socketPath, socketPath.characters.count)
let result = withUnsafePointer(to: &address) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
connect(sockDesc, $0, socklen_t(MemoryLayout<sockaddr>.stride));
}
}
套接字有效,因为在Qt中开发的另一个客户端可以愉快地连接到此路径。
这里有明显的错误,还是应该有效?
答案 0 :(得分:3)
connect()
的第三个参数必须是实际大小
sockaddr_un
的内容,而不是“通用”sockaddr
的内容。
通过一些简单的简化:
var socketPath = "/path/to/socket"
let sockDesc = socket(AF_LOCAL, SOCK_STREAM, 0)
var address = sockaddr_un()
address.sun_family = UInt8(AF_LOCAL)
address.sun_len = UInt8(MemoryLayout<sockaddr_un>.size)
strlcpy(&address.sun_path.0, socketPath, MemoryLayout.size(ofValue: address.sun_path))
let result = withUnsafePointer(to: &address) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
connect(sockDesc, $0, socklen_t(address.sun_len));
}
}
另请注意
strncpy(dataPtr, socketPath, socketPath.characters.count)
代码中的将socketPath.characters.count
个字节复制到
dataPtr
,这有几个原因是错误的:
socketPath.characters.count
不是UTF-8字节的数量
如果字符串包含非ASCII字符, strncpy()
很容易被误用,strlcpy()
(如果有)是
通常是更好的选择。