GCDAsyncSocket has an interesting approach, where you can tell it what you want to read, like a certain number of bytes, or everything up to a specific byte sequence (like CRLF), and it'll call you back when it's read it.
Another approach would be to use synchronous I/O calls, of course, but Cocoa APIs don't make that easy to do. —Jens > On Sep 10, 2015, at 6:12 PM, Adam Kaplan <adk...@gmail.com> wrote: > > It’s amazing how many times we solve this same problem over-and-over. It’s so > difficult because every case is slightly nuanced :( > > I agree with everything Jens said, as usual. A ring buffer is fastest, but if > your max message size is unknown and you can’t do stream-style parsing, > they’ll always be some nasty edge cases… > > Just feeding into an NSMutableData is a good approach too and probably the > most common. There are some downsides, such as multi-threaded parsing > complexity and manually having to manage the addition and removal of data > blocks. > > A third tool in the arsenal is GCDs dispatch_data_t, which is very well > suited for combining, traversing and removing arbitrarily-sized data blocks > in a multi-threaded streaming environment. The downsides there are GCD's > boilerplate overhead and a performance profile that is not always easy to > reason about. > > — adam > > >> On Wednesday, September 9, 2015 at 6:30 PM, Jens Alfke wrote: >> >> >>> On Sep 9, 2015, at 2:07 PM, Motti Shneor <su...@bezeqint.net >>> (mailto:su...@bezeqint.net)> wrote: >>> I need reading messages off the stream, each prefixed by 4 bytes containing >>> its size. I was wondering if it was advisable to first read just the size >>> (4 bytes) then read the rest of the message, or maybe it was better to have >>> a big buffer into which to “drain” the stream, then parse my messages off >>> the buffer? >> >> The first approach won’t work, because the amount of data received is >> unpredictable. For instance you might receive only three bytes, which isn’t >> enough to parse the data size. Or you might be able to read the data size, >> but then try to read a 100000-byte message and get only 1500 bytes of it. >> >> The usual approach when parsing data asynchronously from a network stream is >> to keep a variable-size buffer of unparsed data. When data arrives, you read >> all of it and append it to the buffer; then you try to parse the data in the >> buffer. If there’s not enough to parse yet, you give up till there’s more; >> or if you parse some data, you remove it from the start of the buffer. >> >> So in your case you’d first check whether the buffer has at least four >> bytes; if so, you look at the length, and check whether that many more bytes >> are available. If they are, you read the whole message and remove it from >> the buffer. >> >> An NSMutableData object works well as a buffer, if you’re not too concerned >> about high performance. The fastest implementation is probably some sort of >> custom ring buffer. >> >> —Jens >> _______________________________________________ >> Do not post admin requests to the list. They will be ignored. >> Macnetworkprog mailing list (Macnetworkprog@lists.apple.com >> (mailto:Macnetworkprog@lists.apple.com)) >> Help/Unsubscribe/Update your Subscription: >> https://lists.apple.com/mailman/options/macnetworkprog/adkapx%40gmail.com >> >> This email sent to adk...@gmail.com (mailto:adk...@gmail.com) > > _______________________________________________ Do not post admin requests to the list. They will be ignored. Macnetworkprog mailing list (Macnetworkprog@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/macnetworkprog/archive%40mail-archive.com This email sent to arch...@mail-archive.com