Ruby TCPServer双向数据传输时连接冻结问题如何解决?
Ruby TCPServer双向通信连接冻结问题解决方案
问题根因
- 客户端发送数据后未告知服务端数据传输已结束,服务端的
while line = session.gets会持续阻塞等待新输入,无法进入返回响应的逻辑 - 客户端发送完数据后直接进入读循环等待服务端返回,双方进入死等状态,只有客户端进程终止、连接断开时,服务端的
gets才会返回nil退出循环 - 原服务端代码中存储接收数据的
test变量定义在连接循环外层,多次连接会出现数据累加污染的问题
最简修复方案(单次通信场景)
仅需在客户端发送完数据后关闭写通道,通知服务端数据已全部传输完成即可:
修改后的client.rb
require "socket" socket = TCPSocket.open("localhost", 1234) socket.puts "Sending data.." # 向服务端发送数据 # 新增:关闭写通道,告知服务端没有更多数据要发送 socket.close_write while(line = socket.gets) puts line end # 打印服务端响应 socket.close
优化后的server.rb(修复数据累加问题)
require "socket" server = TCPServer.new 1234 loop do session = server.accept puts "Entering while loop." test = "" # 将变量挪到连接循环内,每次新连接清空数据 while line = session.gets puts "Inside while loop" test << line end puts "Finished reading data" puts "Data received - #{test}" # 读取客户端发送的数据 session.puts "Time is #{Time.now}" # 用puts代替write自动加换行,避免客户端读行阻塞 session.close end
长连接复用场景方案(约定传输结束标记)
如果需要保持连接多次双向通信,可以约定特定标记作为单次传输结束的标识,不需要频繁关闭通道:
server.rb
require "socket" server = TCPServer.new 1234 loop do session = server.accept puts "Entering while loop." test = "" while line = session.gets # 遇到约定的结束标记就退出当前读循环 break if line.chomp == "__END_OF_MSG__" puts "Inside while loop" test << line end puts "Finished reading data" puts "Data received - #{test}" session.puts "Time is #{Time.now}" # 此处如果需要继续复用连接处理后续请求,不要调用session.close session.close end
client.rb
require "socket" socket = TCPSocket.open("localhost", 1234) socket.puts "Sending data.." # 发送约定的结束标记,告知服务端本次数据传输完成 socket.puts "__END_OF_MSG__" while(line = socket.gets) puts line end # 需要发送更多数据可以继续写socket,不需要重建连接 socket.close
内容的提问来源于stack exchange,提问作者SantiArias
相关产品推荐
相关产品推荐

