Socket API

if I would use the Network framework, someone can provide a quick and
easy example of server and client?

Pasted in below is a bunch of snippets from a simple TCP client and server.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple


Client:

var connection: NWConnection?

func start() {
    let connection = NWConnection(host: "example.com", port: 80, using: .tcp)
    connection.stateUpdateHandler = self.stateDidChange(to:)
    self.setupReceive(on: connection)
    connection.start(queue: .main)
    self.connection = connection
}

func stateDidChange(to state: NWConnection.State) {
    switch state {
    case .setup:
        break
    case .waiting(let error):
        self.connectionDidFail(error: error)
    case .preparing:
        break
    case .ready:
        self.status = "Connected"
    case .failed(let error):
        self.connectionDidFail(error: error)
    case .cancelled:
        break
    }
}

Server:

var listener: NWListener?

func start() throws {
    let listener = try NWListener(using: .tcp, on: 12345)
    listener.stateUpdateHandler = self.stateDidChange(to:)
    listener.newConnectionHandler = self.didAccept(connection:)
    listener.start(queue: .main)
    self.listener = listener
}

func stateDidChange(to newState: NWListener.State) {
    switch newState {
    case .setup:
        break
    case .waiting:
        break
    case .ready:
        break
    case .failed(let error):
        self.listenerDidFail(error: error)
    case .cancelled:
        break
    }
}

var nextID: Int = 0

var connectionsHandlers: [Int: ConnectionHandler] = [:]

func didAccept(connection: NWConnection) {
    let handler = ConnectionHandler(connection: connection, uniqueID: self.nextID)
    self.nextID += 1
    self.connectionsHandlers[handler.uniqueID] = handler
    handler.didStopCallback = self.connectionDidStop(_:)
    handler.start()
}

func stop() {
    if let listener = self.listener {
        self.listener = nil
        listener.cancel()
    }
    for handler in self.connectionsHandlers.values {
        handler.cancel()
    }
    self.connectionsHandlers.removeAll()
}

Data transfer:

func setupReceive(on connection: NWConnection) {
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, contentContext, isComplete, error) in
        if let data = data, !data.isEmpty {
            // … process the data …
            self.status = "did receive \(data.count) bytes"
        }
        if isComplete {
            // … handle end of stream …
            self.stop(status: "EOF")
        } else if let error = error {
            // … handle error …
            self.connectionDidFail(error: error)
        } else {
            self.setupReceive(on: connection)
        }
    }
}

func sendStreamOriented(connection: NWConnection, data: Data) {
    connection.send(content: data, completion: .contentProcessed({ error in
        if let error = error {
            self.connectionDidFail(error: error)
        }
    }))
}

func sendEndOfStream(connection: NWConnection) {
    connection.send(content: nil, contentContext: .defaultStream, isComplete: true, completion: .contentProcessed({ error in
        if let error = error {
            self.connectionDidFail(error: error)
        }
    }))
}
7 Likes