Hello,

On 3 ϦԦ 2013, at 22:01 , Joel VanderWerf <joelvanderwerf / gmail.com> wrote:

> On 06/03/2013 12:41 PM, Panagiotis Atmatzidis wrote:
>> 
>> On 3 ϦԦ 2013, at 21:24 , Joel VanderWerf <joelvanderwerf / gmail.com> wrote:
>> 
>>> On 06/03/2013 11:47 AM, Panagiotis Atmatzidis wrote:
>>>> Hello,
>>>> 
>>>> I'm writing a client/server application using TCPSocket and TCPServer. To serialize the objects at this point I use Marshal, since it comes handy.
>>> ...
>>>> What I notice is that connection ends when the '\n' character appears. I think that the issue is me using "@con.gets" method instead of something more appropriate. I tried @con.read but since 'read' method waits for the remote party to send an 'EOF' or close the connection stalls.
>>>> 
>>>> Is there any other method I can use instead of gets? I did a 'methods.sort' but I can't see and I don't know how to read about these methods using "ri". 'ri TCPSocket::getc' for example doesn't work.
>>> 
>>> You can try
>>> 
>>> Marshal.load(conn)
>>> 
>>> on the client side. The Marshal#load method determines just how many bytes to read.
>> 
>> 
>> Worked fine! Thank you! I don't get it thought, could you elaborate a bit?
> 
> Sure (sorry to be cryptic!).
> 
> If you look at the format of marshalled objects, there is always a way to determine how many bytes to expect. In the case of fixed length data, there is a type field followed by the data (floats for example). In the case of strings, arrays, hashes, etc. there are type and length fields followed by the items (which themselves will have type and possibly length fields). So #load always knows either the number of bytes to read or the number of times to iterate to read all the items. Recursively build the object tree, and you're done.
> 
> However, Marshal#load can't know, until this recursion finishes, the total number of bytes. There is no length field for the whole serialized blob. That's why load(sock.read(n)) doesn't work well with marshal.
> 
> Btw, if your objects are just strings, numbers, booleans, hashes, and arrays, then msgpack is a great alternative to marshal. It's not ruby specific, it's fast and compact, and it plays well with non-blocking io.
> 
> Why non-blocking io? You'll notice that if you Marshal.load(conn) and conn takes a long time to send all the bytes, then the thread that called #load is blocked. So, just start a thread per connection. That's fine if you only need a few connections at a time. With msgpack's buffering, it's possible to read only the complete objects from the connection, and then the thread is free to go on to another connection and read. (See msgpack doc for examples.) Btw, the yajl JSON lib does something like this too.
> 
> Cheers!

Thanks for the amazing explanation! 

I will try msgpack since my objects are just strings and arrays :-)


Panagiotis (atmosx) Atmatzidis

email:	atma / convalesco.org
URL:	http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5
--
The wise man said: "Never argue with an idiot. They bring you down to their level and beat you with experience."