Francis,
Thanks, this works quite nicely. With a nice recursive setup I''m able
to
send out the information I need. Here''s my solution, it''s not
clean but it
definitely works:
class ProtoCamera < EventMachine::Connection
def receive_data(data)
puts "Got data! #{data}"
@image_count ||= 0
send_image
end
def send_image
if @image_count < 100
EM.next_tick {
image_name = "images/image-#{@image_count}.jpg"
length = File.size(image_name)
puts "Sending image #{@image_count}: #{length}"
File.open(image_name, "rb") do |file|
send_data "Content-length: #{length}\n"
send_data "\n"
send_data file.read
send_data "\n"
end
@image_count += 1
send_image
}
# Try to keep around 8 frames a second
sleep(1.0 / 8.0)
end
end
end
EventMachine::run {
EventMachine::start_server "localhost", 8080, ProtoCamera
}
Is there a proper way to sleep on this? I have a feeling that pausing direct
execution may not be the best way, but as this is a simple example it
doesn''t seem that harmful.
Jason
On 10/9/07, Francis Cianfrocca <garbagecat10 at gmail.com>
wrote:>
> #send_data buffers outbound data in userland, as you surmised, and
doesn''t
> actually write the network until the next "turn" through the
reactor loop.
>
> So you need to cause the reactor to turn at some point in your processing.
>
>
> The easiest way is probably to use EM#next_tick (documented in the rdoc),
> or a Spawned Process (documented in the file SPAWNED_PROCESSES).
>
> #next_tick was originally designed for throttling the output to remote
> network peers, but your requirement fits well enough.
>
> send_data data
> EM.next_tick { send_more_data }
>
> and then return from your function. The block passed to #next_tick will be
> executed AFTER a pass through the reactor core, which will dispatch the
data
> that has already been passed to send_data.
>
> Make sense? Let me know if it works.
>
> Also, we should cross post this to the EM ML so that others can benefit.
>
> On 10/9/07, Jason Roelofs < jameskilton at gmail.com> wrote:
> >
> > Francis,
> >
> > I''m writing a small server to push "streaming"
image data and I''m kind
> > of stuck. I can''t seem to find a way to force-flush the data
I''ve written to
> > the socket, so it all gets sent after receive_data is done, which
doesn''t
> > work for me.
> >
> > It''s a pseudo MotionJPEG server, looks like this:
> >
> > class ProtoCamera < EventMachine::Connection
> >
> > def receive_data(data)
> > puts "Got data! #{data}"
> > send_images
> > end
> >
> > def send_images
> > @image_count ||= 0
> >
> > while @image_count < 50
> > image_name = "images/image-#{@image_count}.jpg"
> > length = File.size(image_name)
> > puts "Sending image #{@image_count}: #{length}"
> >
> > # Try to keep around 8 frames a second
> > sleep(1.0 / 8.0)
> >
> > File.open(image_name, "rb") do |file|
> > send_data "Content-length: #{length}\n"
> > send_data "\n"
> > send_data file.read
> > send_data "\n"
> >
> > --- NEED TO FLUSH HERE ----
> > end
> >
> > @image_count += 1
> > end
> > end
> > end
> >
> > As it stands, all 50 pieces of image data don''t get sent
until the end.
> > How do I force a socket flush whenever I want?
> >
> > Thanks
> >
> > Jason
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://rubyforge.org/pipermail/eventmachine-talk/attachments/20071009/d5ec7ff7/attachment.html