代码之家  ›  专栏  ›  技术社区  ›  TheDarkKnight

连接到本地插座

  •  3
  • TheDarkKnight  · 技术社区  · 7 年前

    我一直在尝试创建到本地套接字文件的连接,但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 回复  |  直到 7 年前
        1
  •  5
  •   Martin R    2 年前

    的第三个论点 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

    • socketPath.characters.count 如果字符串包含非ASCII字符,
    • 它可能会覆盖目标缓冲区。

    strncpy() 很容易被误用,并且 strlcpy() (如果可用)是