7
votes

I'm making a simple test app using Swift Network framework. One server, one client (both iOS simulators), and successfully established tcp connection between them. I'm trying to send a series of short messages.

Server is sending strings made of natural numbers from 1 to 999. Each number is sent as separate Data, isComplete and contentContext default values are true and .defaultMessage correspondingly.

var count = 0

func send(data: Data) {
    self.connection.send(content: data, completion: .contentProcessed( { error in
        if let error = error {
            self.connectionDidFail(error: error)
            return
        }
        self.count += 1
        let newData = "\(self.count)".data(using: .utf8)!
        if self.count < 1000 {
            self.send(data: newData)
        }
        print("connection \(self.id) did send, data: \(newData as NSData)")
    }))
}

Client is receiving them...

private func setupReceive() {
    nwConnection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, contentContext, isComplete, error) in
        if let data = data, !data.isEmpty {
            print("isComplete: \(isComplete)")
            print("isFinal: \(contentContext.isFinal)")
            let message = String(data: data, encoding: .utf8)
            print("connection did receive, data: \(data as NSData) string: \(message ?? "-" )")
        }
        if let error = error {
            self.connectionDidFail(error: error)
        } else {
            self.setupReceive()
        }
    }
}

... but there is something wrong. Some messages look like their bytes are stuck together (for example consecutive messages "2", "3", "4", "5" could be received like a single message "2345")

For all received messages isComplete equals false and contentContext property isFinal equals true, while .defaultMessage.isFinal should be equal to false.

For now, i'm stuck. Am i just using wrong parameters (I've tried various combinations, but none seems working to me)? Is NWConnection hideously changing messages while sending them?

How can one send a series of separate messages?

1
The first section of code looks odd. You have a guy named 'data' as content. You then create a new variable named 'data' several lines after that.El Tomato
@ElTomato It's just a local variable. While in scope of function, it overrides external variables with the same name (like a function argument). But i will rename it, to make it clear.Sasha Dudkin

1 Answers

0
votes

I am not familiar with this Network framework. But from reading documentation, it seems like you are directly using the transport layer to transmit messages.

Without an application layer protocol, there probably isn't a way for the client to distinguish between different messages. For example, using http as your application protocol has different parameters in the request to identify if its a complete message or not (Content-Length, Content-Encoding, Transfer-Encoding etc...)(Hope an expert can confirm on this)

You may define you own simple protocol so that decoding is possible on client end. For example, you can wrap each message with <Message>your-message</Message> and use it to identify different messages at the client (you will face some drawbacks of something so simple along the way)

There are many things to consider when developing a custom protocol. Better do some reading on this subject if you are serious on it.

Upon further reading, it seems that the following receive is provided:

final func receiveMessage(completion: @escaping (Data?, NWConnection.ContentContext?, Bool, NWError?) -> Void)

... which is able to read complete data. The Discussion section will provide some valuable insight on transport type implications and framing logic required.