You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ruby中通过Socket传输文件?解决无限循环问题

解决Socket文件传输后脚本无限循环的问题

你的三次尝试都存在核心问题:TCP连接未在服务器端主动关闭,或者长度传输逻辑错误,导致客户端的read操作一直阻塞等待数据,无法终止循环。下面逐个分析错误原因,并给出修复方案:

错误原因分析

第一次尝试

服务器写完文件内容后,没有关闭与客户端的连接。TCP是流式协议,客户端的socket.read(1024)会一直尝试从连接中读取数据,只要连接未关闭,就不会返回nil,因此陷入无限循环。

第二次尝试

client.write nil无效,Socket传输的是字节流,无法写入nil值。同时服务器端依然没有关闭连接,客户端的read操作还是会持续阻塞。

第三次尝试

  • 直接写入content.length是将数字转为字符串传输,但客户端用gets读取,gets会一直等待换行符,而服务器端没有写入换行,导致socket.gets永久阻塞。
  • 即使侥幸读到长度,如果文件内容中包含换行符,gets会提前截断,导致读取的长度错误,后续socket.read(length)也会出现问题。

修复方案

方案一:传输完成后主动关闭服务器端Socket

写完文件内容后立即关闭客户端连接,让客户端的read操作返回nil,终止循环:

require 'socket'

server = TCPServer.new 5555

Thread.new do
  client = server.accept
  File.open('files.zip', 'rb') do |file|
    while chunk = file.read(1024)
      client.write(chunk)
    end
  end
  client.close # 关键:传输完成后关闭连接
end

socket = TCPSocket.new('localhost', 5555)
File.open('files_backup.zip', 'wb') do |file|
  while chunk = socket.read(1024)
    file.write(chunk)
  end
end
socket.close

方案二:先传输文件长度(二进制格式)

用二进制打包的方式传输文件长度,避免字符串分隔符的问题,读完指定长度后主动终止操作:

require 'socket'

server = TCPServer.new 5555

Thread.new do
  client = server.accept
  content = File.binread('hackers.zip')
  # 用8字节无符号整数打包文件长度(跨平台兼容)
  client.write([content.length].pack('Q'))
  client.write(content)
  client.close
end

socket = TCPSocket.new('localhost', 5555)
File.open('hackers_backup.zip', 'wb') do |file|
  # 读取8字节的长度数据
  length_bytes = socket.read(8)
  length = length_bytes.unpack('Q')[0]
  # 读取指定长度的文件内容
  content = socket.read(length)
  file.write(content)
end
socket.close

这两种方案都能解决无限循环的问题:第一种通过关闭连接让客户端感知传输结束;第二种通过预先约定的长度,让客户端读取到指定字节后即可终止操作。

内容的提问来源于stack exchange,提问作者user14527579

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 11:22:43