Garbage bytes when reading from socket

Y

yuri.leikind

Hi all,

I am using Ruby to write a simple client program that write some bytes
to a tcp server and then reads bytes.

I have a working version in Java and Perl.

With the Ruby version I have extremely strange behavior - there are
redundant bytes.

It looks like where the Perl and Java client output is 0D 0A, my Ruby
client has 0D 0D 0A. (the server can send both binary and text data,
but it will mostly be used for binary data). The requests sent from all
clients are identical, I checked it many times.

In Perl bytes from the socket are read like this:

while($nr = read($maryDataSocket, $buf, 100000)) {
print STDOUT $buf
or die "Write error on stdout";
}

I do it like this:

while out = maryDataSocket.read(100000)
f.write(out)
end

And yes, before that I do

maryDataSocket.binmode()

bit that doesn't help.

What's wrong?

I use Ruby for Windows (have to :-( ) , version 1.8.2-15

There are some other really weird and frustrating things all related to
IO and \r and \n, but well, I just want to solve this problem. Hell, I
just want to read some bytes from the socket the way the are!

Thank you

Best regards,
Yuri Leikind
 
R

Robert Klemme

Hi all,

I am using Ruby to write a simple client program that write some bytes
to a tcp server and then reads bytes.

I have a working version in Java and Perl.

With the Ruby version I have extremely strange behavior - there are
redundant bytes.

It looks like where the Perl and Java client output is 0D 0A, my Ruby
client has 0D 0D 0A. (the server can send both binary and text data,
but it will mostly be used for binary data). The requests sent from all
clients are identical, I checked it many times.

In Perl bytes from the socket are read like this:

while($nr = read($maryDataSocket, $buf, 100000)) {
print STDOUT $buf
or die "Write error on stdout";
}

I do it like this:

while out = maryDataSocket.read(100000)
f.write(out)
end

And yes, before that I do

maryDataSocket.binmode()

bit that doesn't help.

What's wrong?

I use Ruby for Windows (have to :-( ) , version 1.8.2-15

There are some other really weird and frustrating things all related to
IO and \r and \n, but well, I just want to solve this problem. Hell, I
just want to read some bytes from the socket the way the are!

I'm afraid this is a bit too few information. Are you sure the server
doesn't actually write 0d0d0a and your Perl client just discards the
first 0d - either during reading or printing? Personally I'd try to use
a smaller buffer size - something like 4096. Not that I expect it to
solve your issue but in multithreaded environments it can make a difference.

Other than that, I'd suggest you post a bit more code. You could also
write a simplistic server in Ruby using TCPServer (test with writing
"0d0d0a" and "0d0a") and test both of your scripts against it. HTH

Kind regards

robert
 
Y

yuri.leikind

I'm afraid this is a bit too few information.

Mayby you are right
Are you sure the server
doesn't actually write 0d0d0a and your Perl client just discards the
first 0d - either during reading or printing?

Absolutely. The thing is that the output is actually a wav file. The
perl client produces a valid wav file while the ruby client doesn't.
Personally I'd try to use
a smaller buffer size - something like 4096.

Done it. No effect.
Other than that, I'd suggest you post a bit more code. You could also
write a simplistic server in Ruby using TCPServer (test with writing
"0d0d0a" and "0d0a") and test both of your scripts against it. HTH


Ok. The server is actually a text-to-speech system and it is accessible
in the Internet.

I have simplified both the perl and the ruby client as much as possible
and you can find them below. The algorythm is simple - you open a
socket, write a command and read an id. The open a socket again, write
the id and some natural text message (in case of this publicly
available server the language is german).


=== PERL ===
#!/usr/bin/env perl

use IO::Socket;

$host = "cling.dfki.uni-sb.de";
#$host = "localhost";

$maryInfoSocket = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $host,
PeerPort => 59125);
$maryInfoSocket->autoflush(1);

print $maryInfoSocket "MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE";
#print $maryInfoSocket "MARY IN=TEXT_EN OUT=RAWMARYXML"; # this will
result in text output
print $maryInfoSocket "\015\012";

$id = <$maryInfoSocket>;
chomp $id; chomp $id;

$maryDataSocket = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $host,
PeerPort => 59125);
print $maryDataSocket $id, "\015\012";

#print $maryDataSocket "Hello world";
print $maryDataSocket "Hallo Welt";

print $maryDataSocket "\015\012";

shutdown($maryDataSocket, 1);

open(OUT, ">out.pl.wav");
while($nr = read($maryDataSocket, $buf, 4096)) {
print OUT $buf;
}

===========

=== RUBY ===

#!/usr/bin/env ruby

require 'socket'

host = "cling.dfki.uni-sb.de";
#host = "localhost";

maryInfoSocket = TCPSocket.new(host, 59125)
maryInfoSocket.binmode()

maryInfoSocket.write("MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE")
#maryInfoSocket.write("MARY IN=TEXT_EN OUT=RAWMARYXML") # this will
result in text output

maryInfoSocket.write "\015\012"
maryInfoSocket.flush

id = maryInfoSocket.gets

id.chomp!

maryDataSocket = TCPSocket.new(host, 59125)
maryDataSocket.binmode()

maryDataSocket.write id + "\015\012"
maryDataSocket.flush

#maryDataSocket.write "Hello world" + "\015\012"
maryDataSocket.write "Hallo Welt" + "\015\012"

maryDataSocket.flush
maryDataSocket.close_write


File.open("out.rb.wav", "w"){|f|
while out = maryDataSocket.read(4096)
f.write(out)
end
}

===========

What am I missing here? Why are the results different?

Thank you!

Best regards,
Yuri Leikind
 
R

Robert Klemme

Mayby you are right


Absolutely. The thing is that the output is actually a wav file. The
perl client produces a valid wav file while the ruby client doesn't.


Done it. No effect.

As I said, I don't expect that to cure the issue. :)
Ok. The server is actually a text-to-speech system and it is accessible
in the Internet.

I have simplified both the perl and the ruby client as much as possible
and you can find them below. The algorythm is simple - you open a
socket, write a command and read an id. The open a socket again, write
the id and some natural text message (in case of this publicly
available server the language is german).


=== PERL ===
#!/usr/bin/env perl

use IO::Socket;

$host = "cling.dfki.uni-sb.de";
#$host = "localhost";

$maryInfoSocket = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $host,
PeerPort => 59125);
$maryInfoSocket->autoflush(1);

print $maryInfoSocket "MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE";
#print $maryInfoSocket "MARY IN=TEXT_EN OUT=RAWMARYXML"; # this will
result in text output
print $maryInfoSocket "\015\012";

$id = <$maryInfoSocket>;
chomp $id; chomp $id;

$maryDataSocket = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $host,
PeerPort => 59125);
print $maryDataSocket $id, "\015\012";

#print $maryDataSocket "Hello world";
print $maryDataSocket "Hallo Welt";

print $maryDataSocket "\015\012";

shutdown($maryDataSocket, 1);

open(OUT, ">out.pl.wav");
while($nr = read($maryDataSocket, $buf, 4096)) {
print OUT $buf;
}

===========

=== RUBY ===

#!/usr/bin/env ruby

require 'socket'

host = "cling.dfki.uni-sb.de";
#host = "localhost";

maryInfoSocket = TCPSocket.new(host, 59125)
maryInfoSocket.binmode()

maryInfoSocket.write("MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE")
#maryInfoSocket.write("MARY IN=TEXT_EN OUT=RAWMARYXML") # this will
result in text output

maryInfoSocket.write "\015\012"
maryInfoSocket.flush

id = maryInfoSocket.gets

id.chomp!

maryDataSocket = TCPSocket.new(host, 59125)
maryDataSocket.binmode()

I don't think there is a binmode for sockets - doesn't really seem to
make sense. IMHO sockets are *always* binary.
maryDataSocket.write id + "\015\012"
maryDataSocket.flush

#maryDataSocket.write "Hello world" + "\015\012"
maryDataSocket.write "Hallo Welt" + "\015\012"

maryDataSocket.flush
maryDataSocket.close_write


File.open("out.rb.wav", "w"){|f|

Use file mode "wb" regardless of operating system.
while out = maryDataSocket.read(4096)
f.write(out)
end
}

===========

What am I missing here? Why are the results different?

Another remark: I'd use the block form of TCPSocket.open, like in

TCPSocket.open(host, 59125) do |sock|
...
end

Kind regards

robert
 
Y

yuri.leikind

Thanks a lot!


Robert said:
As I said, I don't expect that to cure the issue. :)


I don't think there is a binmode for sockets - doesn't really seem to
make sense. IMHO sockets are *always* binary.


Use file mode "wb" regardless of operating system.


Another remark: I'd use the block form of TCPSocket.open, like in

TCPSocket.open(host, 59125) do |sock|
...
end

Kind regards

robert
 
Y

yuri.leikind

So it the issue resolved?

Yes! The problem was not in the socket, but in file opening mode.

Thank a lot!

Yuri
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top