From: Victor Reyes Date: 2008-05-29T20:13:20+09:00 Subject: Re: GServer send/receive limit ------=_Part_21572_9639796.1212059606400 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline On Thu, May 29, 2008 at 1:19 AM, Eleanor McHugh < eleanor@games-with-brains.com> wrote: > On 28 May 2008, at 20:08, Victor Reyes wrote: > >> Well, as I said earlier, I found these pieces of code in a website named >> games-with-brains.com, which I think you have something to do with it, >> and >> perhaps it has your picture. >> > > That would be me, and my cruddy code as well so I guess I'd better give you > some help :) > > Attached is the code I lifted from the website: >> >> *THE CLIENT >> >> client = TimeClient.new >> (1..2).each do |i| >> client.connect("localhost", 12341955) >> client.send >> client.on_response >> > > The above line is a bug. My TCPClient class defines send so that it > automatically calls on_response, so calling on_response a second time will > cause the program to hang because the server is still waiting for a request > to respond to. Oddly this isn't apparent in the example provided, which goes > to prove that just because code appears to work doesn't mean it really does. > > Thank goodness we put that disclaimer at the front ;) > > > puts "==========" >> client.disconnect >> sleep 3 >> end >> >> >> THE SERVER: >> cat gs2.rb >> #!/usr/local/ruby-1.8.6/bin/ruby -W0 >> require 'gserver' >> class TestServer < GServer >> def serve( io ) >> begin >> io.puts ">> WELCOME <<" >> loop do >> begin >> telnet_input = io.gets >> puts "The input: #{telnet_input}" >> break if telnet_input =~ /\Aquit\b/ >> cmd = `cat /etc/hosts` >> >> io.puts cmd >> >> if telnet_input.chomp.include? "shutdown" >> self.stop >> end >> io.puts eval(telnet_input) >> rescue Exception >> io.puts "Oops - " + $! >> end >> log "Rec'd " + telnet_input >> end >> io.puts ">> GOODBYE <<" >> io.close >> rescue Exception >> puts "OOPS - " + $! >> raise >> end >> end >> end >> ts = TestServer.new 12341955 >> ts.start >> ts.audit = true >> ts.join >> > > You'll want to do something to restrict the eval, otherwise you have a > potential security black hole, and you don't need the io.close call as that > should be taken care of automatically when the serve method returns. > > THE GLUE THAT KEEPS EVERYTHING TOGETHER, I THINK. Although I don't >> understand it well. >> > > It's basically just an OO wrapper to make writing a TCP client slightly > less tedious. The example provided in the presentation is pretty lousy due > to the time constraints of that medium (we always end up packing in too much > content for a 45 minute session) and a more elegant implementation would > mirror the block version of IO.open, removing the need to explicitly connect > and disconnect. > > cat tcpc.rb >> #!/usr/local/ruby-1.8.6/bin/ruby -W0 >> require 'socket' >> >> EndPoint = Struct.new(:host, :port) >> >> class TCPClient >> attr_reader :remote, :status >> >> def connect remote_host, remote_port >> raise if @socket >> puts "starting client" >> @remote = EndPoint.new(remote_host, remote_port) >> @socket = TCPSocket.new(@remote.host, @remote.port) >> end >> >> def send message >> @socket.puts(message) >> on_response >> end >> >> def on_response; end >> > > The two methods above define a callback mechanism so that an object can > override on_response and this will automatically be called when a message is > sent. Most times this would probably be done by subclassing. > > def receive >> raise unless @socket >> begin >> response = @socket.gets >> end until response >> response >> end >> > > And the begin...end clause here is unnecessary thanks to gets being a > blocking call, so: > > def receive > raise unless @socket > @socket.gets > end > > def disconnect >> @socket.close >> @socket = nil >> end >> end >> > > Anyway, I'll update the presentation to fix the bug and upload a new copy > so that no one else wastes time over it. > > > > Ellie > > Eleanor McHugh > Games With Brains > http://slides.games-with-brains.net > ---- > raise ArgumentError unless @reality.responds_to? :reason > > > > Eleanor, Thank you for taking the time to explain this to me. I truly appreciate it. I'll play with the updated version and see how to use it on my own code. Thanks a bunch! Victor ------=_Part_21572_9639796.1212059606400--