连接到本地套接字。

3

我一直在尝试创建与本地套接字文件的连接,但 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开发的客户端可以愉快地连接到这个路径。这里是否有明显的错误,或者应该可以工作?
1个回答

5
connect() 的第三个参数必须是 sockaddr_un 的实际大小,而不是“通用”的 sockaddr 的大小。稍加简化即为:
let 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 socklen = socklen_t(address.sun_len)

let result = withUnsafePointer(to: &address) {
    $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
        connect(sockDesc, $0, socklen);
    }
}

请注意,还有一个要点。
strncpy(dataPtr, socketPath, socketPath.characters.count)

在您的代码中,将 socketPath.characters.count 个字节复制到 dataPtr 是错误的,原因有几个:

  • 如果字符串包含非ASCII字符,则 socketPath.characters.count 不是UTF-8字节数,
  • 它不能保证目标字符串以空字符结尾,
  • 它可能会覆盖目标缓冲区。

strncpy() 容易被误用,如果可用的话, strlcpy()通常是更好的选择。


谢谢,这正是我在寻找的,也很高兴了解到strlcpy。 - TheDarkKnight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接