连接到本地套接字

时间:2017-06-29 11:09:00

标签: swift sockets

我一直在尝试创建与本地套接字文件的连接,但是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 个答案:

答案 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()(如果有)是 通常是更好的选择。