From: Steve Lewis Date: 2008-09-07T09:58:59+09:00 Subject: Re: Question About TCPServer & TCPSocket classes 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.