【发布时间】:2016-11-23 14:24:43
【问题描述】:
此代码向 www.example.com 网站发送两个 HTTP 请求:
require 'socket'
@host = 'www.example.com'
@port = 80
@path = "/"
# Build HTTP request
def request(close=false)
"GET #{@path} HTTP/1.1\r\nHost: #{@host}#{"\r\nConnection: close" if close}\r\n\r\n"
end
# Build socket
socket = TCPSocket.open(@host,@port) # Connect to server
# Send request twice via socket
2.times {socket.print request}
以下是我找到的各种阅读回复的方法:
# Method 1: close_write and read
socket.close_write # Without this line, the next line hangs
response = socket.read
puts response.length
# Method 2: send another http request with 'Connection: close' header, then use 'read'
socket.print request(true) # Without this line, the next line hangs
response = socket.read
puts response.length
# Method 3: recv
# puts socket.eof? # Method fails when I add this line
r1, r2 = socket.recv(1000000), socket.recv(1000000)
puts r1.length, r2.length
# Method 4: IO.select and read_nonblock
puts socket.eof?
# IO.select([socket]) # The code still works without this IO.select...
r1 = socket.read_nonblock(9999999)
IO.select([socket]) # ...but not without this one
r2 = socket.read_nonblock(9999999)
puts r1.length, r2.length
puts socket.eof? # Hangs for ages before returning 'true'
问题:
- 方法 1 中的 'socket.close_write' 行究竟是做什么的,为什么该方法必须起作用?
- 在方法 2 中,'Connection: close' 标头是否以某种方式实现了与方法 1 中的 'socket.close_write' 行相同的结果?如果不是,它在做什么,为什么需要让其余方法起作用?
- 为什么在方法 3 中添加注释行“puts socket.eof?”会导致其余代码挂起?
- 在方法 3 中,recv 调用如何以及为什么在 HTTP 响应结束时停止(而不是同时接收下一个响应)?
- 为什么方法 4 中的第二个 IO.select 是必须的,而第一个不是?
- IO.select 实际上做了什么?
- 为什么方法 4 中的最后一行“puts socket.eof?”在返回 true 之前会挂起很长时间?
- 是否有一种通用的方法来检查套接字当前期望的响应数量,并从套接字读取该数量的响应,而无需关闭套接字以进行写入?
最后,如果在此处无法回答,是否有一个很好的资源可以让我对以上所有内容有所了解,以及从 TCP 套接字(或一般的网络套接字)读取的一般清晰度?
谢谢。
【问题讨论】: