Re: Understanding NSNetService and peer-to-peer streaming


 


On Aug 20, 2017, at 7:00 PM, Graham Cox <graham@...> wrote:

If I send two ‘messages’ too quickly, they get concatented on the stream, and the receiver can’t tell where the boundary is between the two (or more) messages.

This is a classic newbie networking mistake. (No offense I hope!) TCP is a stream, and there is absolutely no delimiter between writes, and no association between the number of bytes written vs. the number read at the receiver. It's true that if you only intermittently send bytes, the receiver will usually receive the same number of bytes from its read call … but not always, depending on circumstances, because the data can get broken up at arbitrary locations.

To send and receive messages you have to delimit them somehow. The classic ways are to prefix every message with a count, or to have a reserved byte sequence that denotes end-of-message. (Pascal strings and C strings, anyone?) The former is better as long as you know the message length ahead of time. 

So for example, on the sending end just write a 32-bit byte count (big- or little-endian, pick one), then the message. On the receiving end, have a resizable read buffer (an NSMutableData works well) and keep reading bytes into it, growing if necessary. After each read decode the message length at the start, then check if you have that many more bytes in the buffer; if so, hand the message to the higher-level code, then delete the count and the message from the buffer, so what remains starts at the next message boundary. Then check if you've got another complete message, and when you don't, issue another read.

I have a protocol/framework called BLIP that's basically this to the nth power. It does message queueing, multiplexing, high/low priority, message headers (like HTTP), etc. Might be overkill for your needs, but check it out.

—Jens

Join cocoa@apple-dev.groups.io to automatically receive all group messages.