Sending Binary Data?


Y

Yacin Nadji

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:

[email protected]: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
 
Ad

Advertisements

R

Robert Klemme

Yacin said:
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

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.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+")

"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
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:

[email protected]: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
 
Ad

Advertisements

L

Logan Capaldo

--Apple-Mail-11--359922324
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


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 }


--Apple-Mail-11--359922324--
 

Top