NWConnection.receive doesn't return expected data

I'm using an NWConnection to talk to a TCP endpoint. The connection steps are working fine and I'm able to receive some data, but not all the data I expect. I am posting to see if I misunderstand how the NWConnection is supposed to behave.

The messages I want to receive have a header and a payload. The header tells me how many bytes are in the payload. To do that I am trying to call receive twice on the connection. The first receive looks something like

connection.receive(minimumIncompleteLength: MessageHeader.PackedDataCount,
                   maximumLength: MessageHeader.PackedDataCount) { … }

The second receive call is very similar and tries to grab the payload. It looks something like:

let payloadLength = messageHeader.payloadLength
connection.receive(minimumIncompleteLength: payloadLength,
                   maximumLength: payloadLength) { … }

The first message sent by the server has the bytes [0x0F, 0x00, 0x01, 0x02].

The first three bytes are the header and indicate that the message type is 0x0F, of length 1 byte (0x0001) and the payload is one byte, 0x02.

When I run my code, the first call to receive works fine. I get three of the four bytes sent by the server. The second call to receive, however, never returns the one remaining byte (the callback is never invoked).

If I change the first receive call to ask for 1024 as a maximum length then I can see all 4 bytes from the server in the response so I know all the data I want was sent.

But I can't receive it in two subsequent calls to the connection.

Do I misunderstand the way that receive is supposed to behave? If the server sends four bytes, do I have to read them all in one call to receive?

I managed to solve my issue by implementing a custom protocol framer as shown in the 2019 WWDC presentation

Advances in Networking, Part 2

https://developer.apple.com/videos/play/wwdc2019/713?time=779

But I am curious why simply doing two receive calls in a row didn't work.

I managed to solve my issue by implementing a custom protocol framer as shown in the 2019 WWDC presentation

Cool. That’s not a bad option here, because it allows your higher-level code to work in terms of messages rather than bytes.

But I am curious why simply doing two receive calls in a row didn't work.

That’s certainly weird. Are you sure that payloadLength was 1, not 256? The latter is what you’d get if you forgot to convert the length from network byte order.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NWConnection.receive doesn't return expected data
 
 
Q