如何在Ruby中通过套接字复制文件?

huangapple go评论84阅读模式
英文:

How to copy a file over a socket in Ruby?

问题

以下是你提供的代码的中文翻译部分:

第一个示例:

  1. 我尝试通过套接字复制文件。这部分是有效的。但是,脚本从未结束。我一直陷入了一个无休止的while循环中,读取套接字上的数据。非常感谢您的提前帮助。
  2. require 'socket'
  3. server = TCPServer.new 5555
  4. Thread.new do
  5. client = server.accept
  6. file = File.new('files.zip', 'rb')
  7. while line = file.read(1024)
  8. client.write line
  9. end
  10. end
  11. socket = TCPSocket.new('localhost', 5555)
  12. file = File.new('files_backup.zip', 'wb')
  13. while line = socket.read(1024)
  14. file.write line
  15. end

第二个示例:

  1. 我也尝试了使用nil
  2. require 'socket'
  3. server = TCPServer.new 5555
  4. Thread.new do
  5. client = server.accept
  6. client.write File.binread 'files.zip'
  7. client.write nil
  8. end
  9. socket = TCPSocket.new('localhost', 5555)
  10. file = File.new('files_backup.zip', 'wb')
  11. while line = socket.read(1024)
  12. unless line
  13. break
  14. end
  15. file.write line
  16. end
  17. file.close

第三个示例(更新后的,使用数据长度):

  1. 使用读取的长度进行了更新。
  2. require 'socket'
  3. server = TCPServer.new 5555
  4. Thread.new do
  5. client = server.accept
  6. content = File.binread('hackers.zip')
  7. client.write content.length
  8. client.write content
  9. end
  10. socket = TCPSocket.new('localhost', 5555)
  11. file = File.new('hackers_backup.zip', 'wb')
  12. length = socket.gets.to_i
  13. content = socket.read length
  14. file.write content
  15. file.close
英文:

I'm trying to copy a file over a socket. This works. However, the script never ends. I get stuck in an endless while loop reading data over the socket. Thank you so much in advance.

  1. server = TCPServer.new 5555
  2. Thread.new do
  3. client = server.accept
  4. file = File.new('files.zip', 'rb')
  5. while line = file.read(1024)
  6. client.write line
  7. end
  8. end
  9. socket = TCPSocket.new('localhost', 5555)
  10. file = File.new('files_backup.zip', 'wb')
  11. while line = socket.read(1024)
  12. file.write line
  13. end

I tried with nil as well.

  1. require 'socket'
  2. server = TCPServer.new 5555
  3. Thread.new do
  4. client = server.accept
  5. client.write File.binread 'files.zip'
  6. client.write nil
  7. end
  8. socket = TCPSocket.new('localhost', 5555)
  9. file = File.new('files_backup.zip', 'wb')
  10. while line = socket.read(1024)
  11. unless line
  12. break
  13. end
  14. file.write line
  15. end
  16. file.close

Updated with the length as the size of the read.

  1. require 'socket'
  2. server = TCPServer.new 5555
  3. Thread.new do
  4. client = server.accept
  5. content = File.binread('hackers.zip')
  6. client.write content.length
  7. client.write content
  8. end
  9. socket = TCPSocket.new('localhost', 5555)
  10. file = File.new('hackers_backup.zip', 'wb')
  11. length = socket.gets.to_i
  12. content = socket.read length
  13. file.write content
  14. file.close

答案1

得分: 0

  1. 您从未告诉脚本停止阅读。`read(1024)` 函数是阻塞的,在套接字打开的情况下它永远不会返回 nil。最简单的解决方法是在文件发送后关闭套接字。当您不再期望更多数据时,还应关闭文件以写入数据。
  2. 如果您想保持连接,必须使用某种协议。也许可以通过以文件长度开始通信,然后读取第一行,随后从套接字读取预期字节数。
  3. 奖励点是在标头中发送校验和,并在接收时验证文件。
英文:

You never tell the script to stop reading. The read(1024) function is blocking and it never returns nil while the socket is open. Easiest fix would be to close the socket when the file is sent. You should also close the file to write the data when you don't expect more.

  1. require 'socket'
  2. server = TCPServer.new 5555
  3. Thread.new do
  4. client = server.accept
  5. file = File.new('files.zip', 'rb')
  6. while line = file.read(1024)
  7. client.write line
  8. end
  9. client.close
  10. end
  11. socket = TCPSocket.new('localhost', 5555)
  12. file = File.new('files_backup.zip', 'wb')
  13. while line = socket.read(1024)
  14. file.write line
  15. end
  16. file.close

If you want to keep the connection you have to come with some kind of a protocol. Maybe start a communication with a line saying the file length. Then you can read the first line and later read the expected number of bytes from the socket.

  1. require 'socket'
  2. server = TCPServer.new 5555
  3. Thread.new do
  4. client = server.accept
  5. file = File.new('files.zip', 'rb')
  6. client.puts file.size
  7. while line = file.read(1024)
  8. client.write line
  9. end
  10. end
  11. socket = TCPSocket.new('localhost', 5555)
  12. length = socket.gets.to_i
  13. File.open('files_backup.zip', 'wb'){|f| f.write(socket.read(length)) }

Bonus point would be sending a checksum in the header and validating the file upon receive.

huangapple
  • 本文由 发表于 2023年3月8日 18:43:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75671990.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定