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

Reply via email to