我在 Ruby 3.0.2 中组装了一个 TCPServer,我发现我似乎无法在不阻塞的情况下读取整个数据包(直到套接字关闭)。
编辑:我试图做的事情有些混乱 - 我的错 - 所以只是为了帮助澄清:我想阅读到目前为止通过 TCP 连接发送的所有内容。(结束编辑)
我的第一次尝试是:
#!/snap/bin/ruby
require 'socket'
server = TCPServer.new('localhost', 4200)
loop {
Thread.start(server.accept) do |connection|
puts connection.gets # The important line
end
}
但这会挂起,直到客户端关闭连接。好的,所以我看一下connection.methods
, 和 ruby 文档,并尝试了一堆看起来很有希望的选项。基本上,有两种类型的读取方法:阻塞和非阻塞。
我尝试的阻塞方法是.read
, .gets
, .readlines
, .readline
, .recv
, 和.recvmsg
. 现在.read
, .readlines
, 和.gets
所有挂起(直到套接字关闭) - 所以这没有帮助。其他的(例如.readline
,recv
方法)不会阅读整个消息。现在,我可以读取每一行,直到看到一个空行并从那里解析 HTTP 标头。但是必须有更好的方法;我不想担心收到损坏的消息并挂起,因为我没有在标题末尾读取空行。
所以我去看了非阻塞选项。具体.recv_nonblock
和.recvmsg_nonblock
。这两个抛出错误(资源暂时不可用 - recvfrom(2) 将阻塞和资源暂时不可用 - recvmsg(2)分别)。
关于可能发生的事情的任何想法?我认为使用 Ruby 3 与我有关,因为在 Ruby 2.5 上尝试代码client.gets
会返回一行(不会挂起),尽管.readlines
会挂起 - 所以不确定发生了什么。
理想情况下,我可以调用类似的东西client.get_message
,我会得到已发送的整个消息,但我也可以在 TCP 级别工作并获取数据包大小,读取该大小并重建消息从那里。