Question about YAML over sockets

As far as I can tell, YAML.load will not return until the sender closes
the socket. Is this true? If true, is this desirable?

Ken wrote:

As far as I can tell, YAML.load will not return until the sender closes
the socket. Is this true? If true, is this desirable?

If you need to have YAML.load return before you've closed the socket, send a pause indicator "\n...\n". YAML.load will return and you can read further documents from the same IO.

_why

> As far as I can tell, YAML.load will not return until the sender closes
> the socket. Is this true? If true, is this desirable?
>
If you need to have YAML.load return before you've closed the socket,
send a pause indicator "\n...\n". YAML.load will return and you can
read further documents from the same IO.

_why

I tried sending the pause indicator using a variety of plausible IO
methods (write, print, puts, etc.) but without success. The receiver
listed below prints the data but only after five seconds.

Sender:

require "socket"
require "yaml"

data = { 'a' => [1,2,3], 'b' => 43 }
server = TCPServer.new("localhost", 5555)
socket = server.accept
YAML.dump(data, socket)
socket.write "\n...\n"
sleep 5

Receiver:

require "socket"
require "yaml"

socket = TCPSocket.new("localhost", 5555)
data = YAML.load(socket)
p data

The YAML loader tries to read enough to fill its buffer. It might be
better to use IO#readline. The only way to do this for now is to
overload IO#read so it will read a line at a time.

Here's a replacement receiver:

  require "socket"
  require "yaml"
  
  socket = TCPSocket.new("localhost", 5555)
  class << socket
      alias _read read
      def read( len )
          readline
      end
  end
  data = YAML.load(socket)
  p data

Also, the parser isn't stopping at the pause indicator properly and is
requiring an additional newline.

Here's a replacement sender:

  data = { 'a' => [1,2,3], 'b' => 43 }
  server = TCPServer.new("localhost", 5555)
  socket = server.accept
  YAML.dump(data, socket)
  socket.write "\n...\n\n"
  sleep 5

Stream parsing like this is totally untested. Time to remedy the
situation.

_why

···

Ken Collins (pine29@myfastmail.com) wrote:

> > As far as I can tell, YAML.load will not return until the sender closes
> > the socket. Is this true? If true, is this desirable?
> >
> If you need to have YAML.load return before you've closed the socket,
> send a pause indicator "\n...\n". YAML.load will return and you can
> read further documents from the same IO.
>
> _why

I tried sending the pause indicator using a variety of plausible IO
methods (write, print, puts, etc.) but without success. The receiver
listed below prints the data but only after five seconds.

Thanks, _why, that change works for me.

As a Ruby noob, it's a beautiful thing to see that major contributors to
the language are accessible and eager to help. Thanks again.

···

On Wed, 12 Jan 2005 06:03:53 +0900, "why the lucky stiff" <ruby-talk@whytheluckystiff.net> said:

Ken Collins (pine29@myfastmail.com) wrote:
> > > As far as I can tell, YAML.load will not return until the sender closes
> > > the socket. Is this true? If true, is this desirable?
> > >
> > If you need to have YAML.load return before you've closed the socket,
> > send a pause indicator "\n...\n". YAML.load will return and you can
> > read further documents from the same IO.
> >
> > _why
>
> I tried sending the pause indicator using a variety of plausible IO
> methods (write, print, puts, etc.) but without success. The receiver
> listed below prints the data but only after five seconds.
>

The YAML loader tries to read enough to fill its buffer. It might be
better to use IO#readline. The only way to do this for now is to
overload IO#read so it will read a line at a time.

Here's a replacement receiver:

  require "socket"
  require "yaml"
  
  socket = TCPSocket.new("localhost", 5555)
  class << socket
      alias _read read
      def read( len )
          readline
      end
  end
  data = YAML.load(socket)
  p data

Also, the parser isn't stopping at the pause indicator properly and is
requiring an additional newline.

Here's a replacement sender:

  data = { 'a' => [1,2,3], 'b' => 43 }
  server = TCPServer.new("localhost", 5555)
  socket = server.accept
  YAML.dump(data, socket)
  socket.write "\n...\n\n"
  sleep 5

Stream parsing like this is totally untested. Time to remedy the
situation.

_why

Likewise, it's good to see growth. And openness to fledgling
technology. And you did get a bit lucky, I can be so ignorant and
aloof sometimes. Well, stick around.

_why

···

Ken Collins (pine29@myfastmail.com) wrote:

As a Ruby noob, it's a beautiful thing to see that major contributors to
the language are accessible and eager to help. Thanks again.