Ruby 使用 gets 从套接字请求中读取行导致阻塞

Ruby use gets to read lines from a socket request causes blocking

我目前正在研究 ruby 并制作一个支持套接字的服务器。 现在我需要将套接字请求解析为 HTTP METHOD、URI、VERSION、HEADERS 和 BODY.

我了解到 headers 和 body 之间应该有一个空行,即

GET / HTTP/1.1

Host: localhost:8096

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) Gecko/20100101 Firefox/41.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.7,zh-CN;q=0.3

Accept-Encoding: gzip, deflate

Connection: keep-alive

现在我正在尝试读取每一行并通过

解析它
@request = server.accept
while line = @request.gets
    ...
    parse_request_line(line)
    ...
    parse_header(line)
    ...
end

但是,当读入最后一个空行后,while 循环会被 gets 阻塞,因为它正在等待更多的输入。

我尝试将上面的代码修改为

@request = server.accept
while line = @request.gets
    break if line.to_s.strip.length == 0
    ...
    parse_request_line(line)
    ...
    parse_header(line)
    ...
end

看起来可行,当遇到一个空行然后打破循环。 但是,当请求包含 body 时,break 将中断读取请求的其余部分,body.

即 获取 / HTTP/1.1

Host: localhost:8096

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) Gecko/20100101 Firefox/41.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.7,zh-CN;q=0.3

Accept-Encoding: gzip, deflate

Connection: keep-alive
# here is an empty line between headers and body

This is a body .... some contents here
1213123123

然后我尝试了 Socket::recv。好像跟gets一样,会阻塞程序继续执行。 我现在不知道如何解决它。 有什么建议吗?

谢谢!

http 请求的结束通常由 body 的长度定义。这通常通过使用 content-length header 或使用分块传输编码(零大小的块结束请求)来给出。有关详细信息,请参阅 http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4.

没有特别的理由相信请求的结束body会发生和行尾,所以使用gets不是一个好主意。

只使用 read 应该就足够了,但是您需要计算您希望出现的字节数,以便您知道何时读完 body。