Steve Lewis
9/7/2008 1:03:00 AM
On Sat, 06 Sep 2008 11:04:43 +0200, Robert Klemme wrote:
> On 06.09.2008 07:45, Steve Lewis wrote:
>> Hello Rubyists,
>>
>> I've been messing around with socket programming in Ruby lately, and
>> I've hit a snag with some of my experiments. My first, (successful),
>> experiment was to create a basic client/server script wherein the
>> client sends a string to the server, and the server responds by simply
>> writing the string back to the client...that code is as follows:
>>
>> Server:
>> ##################################### require 'socket'
>>
>> class PingServer < TCPServer
>>
>> def start_server
>> loop do
>> Thread.start(self.accept) do |s|
>> p "Connection accepted from server #{s.inspect}" request =
>> s.readline.gsub(/\n$/, '')
>> p "Request was #{request}"
>> s.write "Your request was as follows: #{request}" s.write
>> Time.now if request == 'time' s.close
>> p "Connection #{s} closed"
>> end
>> end
>> end
>>
>> end
>>
>> PingServer.new('localhost', 3000).start_server
>>
>> ###############################################
>>
>>
>>
>> The client code is thus:
>> ########################################
>> require 'socket'
>>
>>
>>
>> def send_message(message)
>> TCPSocket.open('localhost', 3000) do |client|
>> client.write(message)
>> stuff = client.read(100)
>> client.close
>> p stuff
>> get_message
>> end
>> end
>>
>> def get_message
>> message = gets
>> send_message(message) unless message.gsub(/\n/, '') == 'quit' exit
>> end
>>
>>
>> get_message
>>
>> ##################################
>>
>> As I said, the above code works as expected, I start the server, then
>> run the client program...I can send strings to the server all day long,
>> and the server writes them right back to me.
>>
>> The problem occurs when I try to send the following instead of a
>> string:
>>
>> Marshal.dump(%w(foo bar baz))
>>
>> Sending the resulting string over the wire causes the server to
>> hang...it doesn't return the string back to the client...I'm at a loss
>> to figure out why it seems to have trouble handling the string...
>>
>> Ideas would be appreciated!!
>
> Steve, you are mixing #read, #write on one side and #readline on the
> other side. Since Marshal.dump creates binary data your #readline on
> the server won't properly work. You should either use a binary
> protocoll *or* a textual (line based) protocol. Mixing both causes
> problems.
>
> Just an additional note: if you use Marshal, you can directly read to
> and write from the socket without the intermediate String. This is
> likely more efficient and also you avoid the issue of not knowing how
> long the Marshal sequence is.
>
> And yet another note: just in case you need a solution with
> communicating processes where all of them are Ruby applications you can
> use DRuby. But I guess at the moment you want to learn about Ruby
> socket programming so this is probably just for keeping in the back of
> your head.
>
> Kind regards
>
> robert
Robert,
Thanks for the help! You're correct, my curiosity here is mostly
academic, but DRuby looks like the practical solution to use when I
decide I'd like to try something more substantial.