Robert Klemme
2/28/2006 9:07:00 AM
Yacin Nadji wrote:
> 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:
>
> 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