CFSocket in Swift (4)

2.5k Views Asked by At

I try to establish a connection to a TCP server, unfortunately without success. Here is my actual way. Does anyone knows, where the error is? I'm getting the error at CFSocketConnectToAddress (I get the .error result, so my code results in the error while connecting print).

Any ideas?

    host = "192.168.0.20"
    port = 8888
    socket = CFSocketCreate(kCFAllocatorDefault,
                            AF_INET,
                            SOCK_STREAM,
                            IPPROTO_TCP,
                            CFSocketCallBackType.readCallBack.rawValue, { (socket: CFSocket?, callBackType: CFSocketCallBackType, address: CFData?, data: UnsafeRawPointer?, info: UnsafeMutableRawPointer?) -> Void in print("callback test") }, nil)
    if socket == nil {
        print("Error while creating socket")
    } else {
        var sin = sockaddr_in(
            sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
            sin_family: sa_family_t(AF_INET),
            sin_port: in_port_t(port),
            sin_addr: in_addr(s_addr: inet_addr(host)),
            sin_zero: (0,0,0,0,0,0,0,0)
        )
        addressData = NSData(bytes: &sin, length: MemoryLayout.size(ofValue: sin)) as CFData
        let connectResult: CFSocketError = CFSocketConnectToAddress(socket, addressData!, 10)
        switch connectResult {
        case .success:
            print("Connected")
        case .error:
            print("Error while connecting")
        case .timeout:
            print("Timeout while connecting")
        }
1

There are 1 best solutions below

0
On

The problem was the port! The htons macro is not available in swift. This is the working way now:

func connectToServer(timeout: Int=10) throws {
    // check, if address is valid https://linux.die.net/man/3/inet_makeaddr
    let inAddr = inet_addr(host)
    if inAddr == INADDR_NONE {
        throw SocketError.noValidAddress
    }

    let socket = CFSocketCreate(kCFAllocatorDefault,
                                AF_INET,
                                SOCK_STREAM,
                                IPPROTO_TCP,
                                CFSocketCallBackType.readCallBack.rawValue,
                                { (socket, callBackType, address, data, info) in
                                    TCPClientCallBack(socket: socket, callBackType: callBackType, address: address, data: data, info: info)
                                },
                                nil)
    if socket == nil {
        throw SocketError.socketCreationFailed
    }

    var sin = sockaddr_in() // https://linux.die.net/man/7/ip
    sin.sin_len = __uint8_t(MemoryLayout.size(ofValue: sin))
    sin.sin_family = sa_family_t(AF_INET)
    sin.sin_port = UInt16(port).bigEndian
    sin.sin_addr.s_addr = inAddr

    let addressDataCF = NSData(bytes: &sin, length: MemoryLayout.size(ofValue: sin)) as CFData

    let socketErr = CFSocketConnectToAddress(socket, addressDataCF, CFTimeInterval(timeout))
    switch socketErr {
    case .success:
        print("connected")
    case .error:
        throw SocketError.connectionError
    case .timeout:
        throw SocketError.connectionTimeout
    }
}

enum SocketError: Error {
    case noValidAddress
    case socketCreationFailed
    case connectionError
    case connectionTimeout
}