TCPSocket, send always transmit an even length message

Hello all :slight_smile:

Just a quick and obscure bug report

Console 1:

$ irb

require ‘socket’
=> true
s = TCPSocket.open(‘localhost’, 2000)
=> #<TCPSocket:fd 3>
s.send(‘ab’, 2)
=> 2
s.send(‘cde’, 3)
=> 3

Console 2:
$ nc -l 2000
abcd

Write seems to work OK and puts too, but I could swear I had the same
issue with puts on another Ubuntu box with same specs and ruby 1.8.7.
I’m using Ubuntu 10.10, 2.6.35-27 kernel and ruby 1.9.2-p180 and ruby
1.8.7.

…this is not a flushing issue btw, adding flush at the end yields the
same result (letter e never shows up).

I think you’re using the wrong method.

‘send’ is a inherited method of BasicSocket, and calls ‘sendto’ in the
underlying O/S. And the second argument is actually flags, not length.

/*

  • call-seq:
  • basicsocket.send(mesg, flags [, dest_sockaddr]) => numbytes_sent
  • send mesg via basicsocket.
  • mesg should be a string.
  • flags should be a bitwise OR of Socket::MSG_* constants.
  • dest_sockaddr should be a packed sockaddr string or an addrinfo.
  • TCPSocket.open(“localhost”, 80) {|s|
  • s.send "GET / HTTP/1.0\r\n\r\n", 0
    
  • p s.read
    
  • }
    */

Try setting flags to zero instead and it’ll probably work:

require ‘socket’
=> true

rx = TCPServer.new(‘127.0.0.1’,2000)
=> #TCPServer:0x7f354d04cd68

tx = TCPSocket.new(‘127.0.0.1’,2000)
=> #TCPSocket:0x7f354d03e6c8

s = rx.accept
=> #TCPSocket:0x7f354d033ca0

tx.send(‘ab’, 0)
=> 2

tx.send(‘cde’, 0)
=> 3

s.readpartial(1024)
=> “abcde”

RUBY_DESCRIPTION
=> “ruby 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux]”

But really you should just be using ‘write’ not ‘send’, unless you’re
trying to do something funky like sending out-of-band data (MSG_OOB)