Socket problem

B

Ben Armstrong

Hi,

We're having problems with the standard Socket module with Ruby. It has
been alleged that this might be a C Runtime issue. But this seems
unlikely in light of the fact that other ports on the same platform --
notably Perl, and perhaps also Python -- have working sockets, also
implemented on top of the same C Runtime.

Can someone shed some light on what may be going on?

Here is a failing case, as we first reported the problem:

client.rb:
require 'socket'
s=TCPSocket.new("localhost", ARGV[0])
s.puts("test\r\n")
puts s.gets
s.puts("Blah, blah\r\n")
puts s.gets
s.close

server.rb:
require 'socket'
gs = TCPServer.open(0)
printf("server is on port %d\n", gs.addr[1])
s=gs.accept
line = s.gets
puts("Got line: #{line}")
s.puts(line.upcase)
bl = s.gets
puts ("Got str2: #{bl}")
s.puts(bl.upcase)
s.close

On Linux (ruby 1.8.2), this gave the following output, as expected:
(client side)
TEST
BLAH, BLAH
(server side)
server is on port 40050
Got line: test
Got str2: Blah, blah

On OpenVMS (ruby 1.8.1), this surprisingly gave the following output:
(client side)
test
test
(server side)
server is on port 49379
Got line: test
Got str2: test

We tried varying the test by changing our puts to write on the client
side, but the test results were the same on both platforms.

Thanks,
Ben Armstrong
 
A

Ara.T.Howard

Hi,

We're having problems with the standard Socket module with Ruby. It has
been alleged that this might be a C Runtime issue. But this seems
unlikely in light of the fact that other ports on the same platform --
notably Perl, and perhaps also Python -- have working sockets, also
implemented on top of the same C Runtime.

i'm guessing you are using 'print' in the perl version and, therefore, not
sending a bunch of extra newlines as the code below is doing do to 'puts'?
not sure why that'd make a difference but...

-a
Can someone shed some light on what may be going on?

Here is a failing case, as we first reported the problem:

client.rb:
require 'socket'
s=TCPSocket.new("localhost", ARGV[0])
s.puts("test\r\n")
puts s.gets
s.puts("Blah, blah\r\n")
puts s.gets
s.close

server.rb:
require 'socket'
gs = TCPServer.open(0)
printf("server is on port %d\n", gs.addr[1])
s=gs.accept
line = s.gets
puts("Got line: #{line}")
s.puts(line.upcase)
bl = s.gets
puts ("Got str2: #{bl}")
s.puts(bl.upcase)
s.close

On Linux (ruby 1.8.2), this gave the following output, as expected:
(client side)
TEST
BLAH, BLAH
(server side)
server is on port 40050
Got line: test
Got str2: Blah, blah

On OpenVMS (ruby 1.8.1), this surprisingly gave the following output:
(client side)
test
test
(server side)
server is on port 49379
Got line: test
Got str2: test

We tried varying the test by changing our puts to write on the client
side, but the test results were the same on both platforms.

Thanks,
Ben Armstrong

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| When you do something, you should burn yourself completely, like a good
| bonfire, leaving no trace of yourself. --Shunryu Suzuki
===============================================================================
 
T

ts

B> We're having problems with the standard Socket module with Ruby.

Try to use IO#sync=


Guy Decoux
 
B

Ben Armstrong

B> We're having problems with the standard Socket module with Ruby.

Try to use IO#sync=

That didn't help. Besides, sync is set to true by default.

However, I did pull out a packet sniffer and found out something very
interesting. It appears that for each operation, the old contents of the
buffer is not being overwritten! Instead, it just keeps getting appended
to.

Thus, when I send the first line, I am sending "test\r\n". The server
receives this, and writes back "test\r\n\TEST\r\n". Since my client only
does a gets on the one line expected, it displays "test\r\n".

My "fixed" versions (not really fixed, but demonstrate the problem
clearly) are as follows:

-- client.rb --
require 'socket'
s=TCPSocket.new("localhost", ARGV[0])
s.puts("test\r\n")
printf("garbage: %s",s.gets)
puts s.gets
s.puts("Blah, blah\r\n")
printf("garbage: %s",s.gets)
printf("garbage: %s",s.gets)
printf("garbage: %s",s.gets)
puts s.gets
s.close
-- end client.rb --

-- server.rb --
require 'socket'
gs = TCPServer.open(0)
printf("server is on port %d\n", gs.addr[1])
s=gs.accept
line = s.gets
s.flush
puts("Got line: #{line}")
s.puts(line.upcase)
bl = s.gets
puts ("Got str2 (garbage): #{bl}")
bl = s.gets
puts ("Got str3 (garbage): #{bl}")
bl = s.gets
puts ("Got str4: #{bl}")
s.puts(bl.upcase)
s.close
-- end server.rb --

The output on the server side is:

server is on port 50507
Got line: test
Got str2 (garbage): test
Got str3 (garbage): TEST
Got str4: Blah, blah

The output on the client side is:

garbage: test
TEST
garbage: test
garbage: TEST
garbage: Blah, blah
BLAH, BLAH

Ignoring the lines marked "garbage" we can now see the intended output:

TEST
BLAH, BLAH

How strange, eh? OK, how do I discard the buffer between operations? Or
do I need the developer of the port to help me with this?

Ben
 
E

Edgardo Hames

That didn't help. Besides, sync is set to true by default.

However, I did pull out a packet sniffer and found out something very
interesting. It appears that for each operation, the old contents of the
buffer is not being overwritten! Instead, it just keeps getting appended
to.

Thus, when I send the first line, I am sending "test\r\n". The server
receives this, and writes back "test\r\n\TEST\r\n". Since my client only
does a gets on the one line expected, it displays "test\r\n".

Hi Ben. I might be completely wrong with this one, but have you tried
removing the "\r\n" at the end of the messages? Doesn't #puts add the
newline for you. I believe that could be it.

Regards,
Ed
 
B

Ben Armstrong

Hi Ben. I might be completely wrong with this one, but have you tried
removing the "\r\n" at the end of the messages? Doesn't #puts add the
newline for you. I believe that could be it.

I'm reporting what I'm seeing with the packet sniffer. If what you say is
true, I would see "\r\n\r\n". But that's not what's getting sent. I only
see a single "\r\n" pair at the end of each line.

In earlier tests, before I started working on the problem, I understand we
tried various different variations: puts vs. write, newline, no newline,
etc. None of this affected the issue with the buffer not being overwritten
with the new data.

Ben
 
B

Ben Armstrong

It has
been alleged that this might be a C Runtime issue. But this seems
unlikely in light of the fact that other ports on the same platform --
notably Perl, and perhaps also Python -- have working sockets, also
implemented on top of the same C Runtime.

I guess the factor we probably didn't consider is that although these
languages use the same C Runtime, they may not all use it in the same way,
so now my question is, given the following findings, how can our Ruby port
be fixed so that it behaves like Perl?

What I've found out is that if I follow each 'gets' and 'puts' with
'fsync', the output from my test is as expected on OpenVMS:

-- server.rb --
require 'socket'
gs = TCPServer.open(0)
printf("server is on port %d\n", gs.addr[1])
s=gs.accept
line = s.gets
s.fsync
puts("Got line: #{line}")
s.puts(line.upcase)
s.fsync
bl = s.gets
s.fsync
puts ("Got str2: #{bl}")
s.puts(bl.upcase)
s.fsync
s.close
-- end server.rb --

-- client.rb --
require 'socket'
s=TCPSocket.new("localhost", ARGV[0])
s.puts("test\r\n")
s.fsync
puts s.gets
s.fsync
s.puts("Blah, blah\r\n")
s.fsync
puts s.gets
s.fsync
s.close
-- end client.rb --

Ruby's IO module sets the buffer to _IOFBF via setvbuf. I don't see any
such construct in the Perl source. Is there a reason Ruby is doing this
and Perl isn't?

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Chat client 4
socket programming...lsof? 9
problem with sockets 12
TCP/IP in Ruby 4
socket programming 8
Threaded Socket communication problem. 5
socket data sending problem 2
Java socket programming 1

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top