如果最后尝试IP4v localhost连接失败

时间:2016-01-07 10:39:21

标签: swift macos sockets ipv6 ipv4

我正在尝试连接到我的机器上的localhost(OS-X 10.11.2)

这是代码:

static func initClient(address address: String, port: String) -> InitClientResult {


// General purpose status variable, used to detect error returns from socket functions

var status: Int32 = 0


// ================================================================
// Retrieve the information we need to create the socket descriptor
// ================================================================

// Protocol configuration, used to retrieve the data needed to create the socket descriptor

var hints = addrinfo(
    ai_flags: AI_PASSIVE,       // Assign the address of the local host to the socket structures
    ai_family: AF_UNSPEC,       // Either IPv4 or IPv6
    ai_socktype: SOCK_STREAM,   // TCP
    ai_protocol: 0,
    ai_addrlen: 0,
    ai_canonname: nil,
    ai_addr: nil,
    ai_next: nil)


// For the information needed to create a socket (result from the getaddrinfo)

var servinfo = UnsafeMutablePointer<addrinfo>()


// Get the info we need to create our socket descriptor

status = getaddrinfo(
    address,              // The IP or URL of the server to connect to
    port,                 // The port to which will be transferred
    &hints,               // Protocol configuration as per above
    &servinfo)            // The created information


    SocketUtils.logAddrInfoIPAddresses(servinfo, atLogLevel: .DEBUG, source: "SocketUtils.initClient")

    // Cop out if there is an error

    if status != 0 {
        var strError: String
        if status == EAI_SYSTEM {
            strError = String(UTF8String: strerror(errno)) ?? "Unknown error code"
        } else {
            strError = String(UTF8String: gai_strerror(status)) ?? "Unknown error code"
        }
        return .ERROR(strError)
    }


    // ============================
    // Create the socket descriptor
    // ============================

    let socketDescriptor = socket(
        servinfo.memory.ai_family,      // Use the servinfo created earlier, this makes it IPv4/IPv6 independant
        servinfo.memory.ai_socktype,    // Use the servinfo created earlier, this makes it IPv4/IPv6 independant
        servinfo.memory.ai_protocol)    // Use the servinfo created earlier, this makes it IPv4/IPv6 independant


    // Cop out if there is an error

    if socketDescriptor == -1 {
        let strError = String(UTF8String: strerror(errno)) ?? "Unknown error code"
        freeaddrinfo(servinfo)
        return .ERROR(strError)
    }


    // =====================
    // Connect to the server
    // =====================


    // Start with the first server address/port and work down the list in case of failures.

    for (var info = servinfo; info != nil; info = info.memory.ai_next) {


        // For logging only, remove if the SwifterLog instance "log" is not available or replace by your own logger.

        let (address, service) = sockaddrDescription(info.memory.ai_addr)
        let laddress = address ?? "nil"
        let lservice = service ?? "nil"
        log.atLevelNotice(id: socketDescriptor, source: "SocketUtils.initClient", message: "Trying to connect to \(laddress) at port \(lservice)")


        // Attempt to connect

        status = connect(socketDescriptor, info.memory.ai_addr, info.memory.ai_addrlen)


        // Break if successful, log on failure.
        // TODO: Remove if the SwifterLog instance "log" is not available or replace by your own logger.

        if status == 0 {
            log.atLevelNotice(id: socketDescriptor, source: "SocketUtils.initClient", message: "Connection established")
            break
        } else {
            let strError = String(UTF8String: strerror(errno)) ?? "Unknown error code"
            log.atLevelNotice(id: socketDescriptor, source: "SocketUtils.initClient", message: "Failed to connect with error: \(strError)")
        }
    }


    // Cop out if there is still an error

    if status != 0 {
        let strError = String(UTF8String: strerror(errno)) ?? "Unknown error code"
        freeaddrinfo(servinfo)
        return .ERROR(strError)
    }



    // ===============================
    // Don't need the servinfo anymore
    // ===============================

    freeaddrinfo(servinfo)


    // Ready to start calling send(), return the socket

    return .SOCKET(socketDescriptor)
}

如果我这样称呼:

initClient(address: "127.0.0.1", port: "80")

代码按预期工作。 但是当我把它称为:

initClient(address: "localhost", port "80")

完全无法连接。

生成的调试输出告诉我,在第一种情况下,我使用127 ... getaddrinfo只返回一个addrinfo元素:

DEBUG    : 00000000, SocketUtils.initClient, No: 0, HostIp: 127.0.0.1 at port: 2043
NOTICE   : 00000008, SocketUtils.initClient, Trying to connect to 127.0.0.1 at port 2043
NOTICE   : 00000008, SocketUtils.initClient, Connection established

第一个DEBUG行来自“logAddrInfoIpAddresses”。 当我第二次使用“localhost”调用它时,调试输出如下:

DEBUG    : 00000000, SocketUtils.initClient, No: 0, HostIp: ::1 at port: 2043
DEBUG    : 00000000, SocketUtils.initClient, No: 1, HostIp: fe80::1%lo0 at port: 2043
DEBUG    : 00000000, SocketUtils.initClient, No: 2, HostIp: 127.0.0.1 at port: 2043
NOTICE   : 0000000a, SocketUtils.initClient, Trying to connect to ::1 at port 2043
NOTICE   : 0000000a, SocketUtils.initClient, Failed to connect with error: Connection refused
NOTICE   : 0000000a, SocketUtils.initClient, Trying to connect to fe80::1%lo0 at port 2043
NOTICE   : 0000000a, SocketUtils.initClient, Failed to connect with error: Invalid argument
NOTICE   : 0000000a, SocketUtils.initClient, Trying to connect to 127.0.0.1 at port 2043
NOTICE   : 0000000a, SocketUtils.initClient, Failed to connect with error: Invalid argument

这两个问题是: 1)为什么不连接IPv6地址和2)为什么IPv4地址连接尝试第二次失败?

0 个答案:

没有答案