Forum: Ruby Sending Binary Data?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
355bdded99c705ffa8cd1f21ed4d03af?d=identicon&s=25 Yacin Nadji (Guest)
on 2006-02-28 09:53
(Received via mailing list)
Hello Ruby Gurus!

My friend and I are writing a chat/IM client in Ruby. It's nothing
special, but it's helping us learn the language, especially the lower
level networking parts really well and I'm thoroughly enjoying the
project so far. I thought implementing file transfers would be pretty
nifty, but I'm running into some problems. I did a simple copy by
reading the file (a picture) and adding the lines to a string, and
writing that string out to a new file:

a = String.new

IO.foreach("lighter.jpg") do |line|
  a += line
end

file = File.open("new.jpg","w")
file.write(a)
file.close

And it worked swimmingly, however, when I tried to do this over a
TCPClient/Server:

server.rb

require 'socket'
port = 9191
file = File.open("omgnew.jpg","w+")
server = TCPServer.new('localhost', port)
while session = server.accept
  file.write(session.gets)
  server.close
  file.close
end

client.rb

require 'socket'

server = TCPSocket.new('localhost',9191)
file = String.new
IO.foreach("lighter.jpg") do |line|
  file += line.chomp
end

server.send(file,0)


It works for a bit, then I get this error:

server.rb:7:in `accept': closed stream (IOError)
        from server.rb:7

The file sizes are nearly identical, I'm off by 479 bytes:

ynadji@onizuka:file_transfer$ du -b *
122753  lighter.jpg
122274  omgnew.jpg

Any ideas? I could be doing this entirely wrong, searching didn't yield
any helpful results, so I figured I'd turn here. I was reading around
with Array#pack and String#unpack which seems to be heading in the right
direction, but I'm completely lost :P.

Thanks!

Yacin Nadji
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-02-28 10:09
(Received via mailing list)
Yacin Nadji wrote:
> a = String.new
>
> IO.foreach("lighter.jpg") do |line|
>   a += line
> end

This approach is quite inefficient in two ways:

 - you use + for string concatenation which constantly creates new
objects
and throws old ones away.  Better use <<

 - You need to keep the whole file in mem while with a streaming
approach
(reading and writing a chunk at a time only) you can deal with arbitrary
sized files without worrying about memory.

> file = File.open("new.jpg","w")

You should use mode "wb" - even if on Linux.

> file = File.open("omgnew.jpg","w+")
"wb" again...

> server = TCPServer.new('localhost', port)
> while session = server.accept
>   file.write(session.gets)

Better use #read and #write instead of gets!

>   server.close
>   file.close
> end
>
> client.rb
>
> require 'socket'
>
> server = TCPSocket.new('localhost',9191)

You want TCPServer here.

> file = String.new
> IO.foreach("lighter.jpg") do |line|
>   file += line.chomp
> end

# untested
srv = TCPServer.new('localhost',9191)

while ( sess = srv.accept )
  Thread.new(sess) do |session|
   File.open("lighter.jpg", "rb") |io|
     session.write(io.read(1024))
   end
  end
end

> ynadji@onizuka:file_transfer$ du -b *
> 122753  lighter.jpg
> 122274  omgnew.jpg
>
> Any ideas? I could be doing this entirely wrong, searching didn't
> yield any helpful results, so I figured I'd turn here. I was reading
> around with Array#pack and String#unpack which seems to be heading in
> the right direction, but I'm completely lost :P.

Hope I could give some valuable hints.

Kind regards

    robert
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-03-01 03:52
(Received via mailing list)
On Feb 28, 2006, at 3:52 AM, Yacin Nadji wrote:

> server = TCPSocket.new('localhost',9191)
> file = String.new
> IO.foreach("lighter.jpg") do |line|
>  file += line.chomp
> end

try deleting the .chomp. Jpg's aren't really line oriented anyway.
Also if  you are on windows not opening the file in binary mode will
wreak also sorts of havoc. As an alternative try this:

a = File.open("lighter.jpg", "rb") { |f| f.read }
This topic is locked and can not be replied to.