Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby套接字库Gets方法的澄清_Ruby_Sockets_Http_Httprequest - Fatal编程技术网

Ruby套接字库Gets方法的澄清

Ruby套接字库Gets方法的澄清,ruby,sockets,http,httprequest,Ruby,Sockets,Http,Httprequest,我正在做一项作业,我必须使用socket库用Ruby开发一个web服务器。我能够建立一个简单的web服务器并运行,如本文所示 我目前正在将HTTP请求主体获取并存储到web服务器中的变量中。我遇到的问题是试图定义一个while循环,该循环获取HTTP请求的整个主体 我试图使用gets方法获取HTTP请求的主体。我找不到有关此方法的任何文档(我看到它正在使用) 我想知道是否有更多的在线文档 在我的第一篇帖子中,有人建议我使用Content-Length标题来确定主体的大小以及从套接字读取多少数据。

我正在做一项作业,我必须使用
socket
库用Ruby开发一个web服务器。我能够建立一个简单的web服务器并运行,如本文所示

我目前正在将HTTP请求主体获取并存储到web服务器中的变量中。我遇到的问题是试图定义一个
while
循环,该循环获取HTTP请求的整个主体

我试图使用
gets
方法获取HTTP请求的主体。我找不到有关此方法的任何文档(我看到它正在使用) 我想知道是否有更多的在线文档

在我的第一篇帖子中,有人建议我使用
Content-Length
标题来确定主体的大小以及从套接字读取多少数据。我真的不明白我将如何实现它,因为我不确定
方法是如何实现的


因为这是一个作业,我不认为张贴代码将是一个好主意。我正在寻找有关
gets
方法的更多信息和任何提示,以便为我指明正确的方向。

您的最终问题与gets无关,甚至与代码中的任何内容都无关。但是在我们开始之前,让我们回答这个问题&稍微探索一下套接字

如果你沿着这条链往上走,你会发现Ruby继承了它的。这是
IO
<代码>获取
将逐行读取,直到没有其他内容可读取为止。让我们创建一个简单的客户端,它连接到一个端口,吐出4行诗句,然后退出:

# poetry_sender.rb
require 'socket'

poem = ["'God save thee, ancient Mariner!",
        "From the fiends, that plague thee thus!—",
        "Why look'st thou so?'—With my cross-bow",
        "I shot the ALBATROSS."]

puts "Client establishing connection..."
s = TCPSocket.new 'localhost', 2000

puts "Client sending poetry..."
poem.each { |line| s.puts line } # Print each line out on the socket

s.close # Close our socket
puts "All done."
还有一个简单的服务器,显示客户端发送给我们的内容:

# poetry_receiver.rb
require 'socket'

server = TCPServer.new 2000 # Server bind to port 2000

loop do
  puts "Server now awaiting some poetry..."
  socket = server.accept    # Wait for a client to connect
  while line = socket.gets
    puts "A client sent us this beautiful line: #{line}"
  end
  puts "They had nothing more to say; let's disconnect them."
  socket.close
end
如果先运行服务器(
poetry\u receiver.rb
),然后运行客户端,您将看到如下输出:

Server now awaiting a connection...
A client sent us this beautiful line: 'God save thee, ancient Mariner!
A client sent us this beautiful line: From the fiends, that plague thee thus!—
A client sent us this beautiful line: Why look'st thou so?'—With my cross-bow
A client sent us this beautiful line: I shot the ALBATROSS.
They had nothing more to say; let's disconnect them.
Server now awaiting a connection...
最后两行是重要的一行;它们表示,
socket.get
返回了
nil
,我们退出了
while
循环

那么,我们如何修改我们的
诗歌\u sender.rb
,使服务器不会检测到诗歌的结尾呢?您可能认为这与空行有关,但如果您设置
poem=[]
poem=[”“,”“,”“]
,您会发现它仍然断开连接。但是,如果我们在关闭
poetry\u sender.rb
中的套接字之前添加了延迟,会怎么样

sleep 60
s.close # Close our socket
puts "All done."
现在您将看到服务器输出中出现了很大的延迟。在TCP客户端关闭其套接字之前,TCP服务器不会中断其
while
循环


现在,我们可以转向更广泛的问题:您试图实现一个简单的HTTP服务器,但当您尝试通过web浏览器连接时,服务器在
while
循环中挂起。这是因为您的web浏览器保持该套接字打开但它必须这样做,否则它无法向您返回响应。那么,我们如何知道客户何时完成向我们发送响应?委员会:

客户端以请求消息的形式向服务器发送HTTP请求。。。后面是标题字段一条空行,指示标题部分的结尾,最后是包含有效负载正文(如果有)的消息正文

让我们不要担心消息体;我们如何编写一个
while
循环,如果它没有更多的影响,或者如果它收到一个空行,它将终止?这里有一种方法,在一个简单的HTTP服务器中,无论收到什么请求,都只发送回“Hello world”:

require 'socket'

server = TCPServer.new('localhost', 2345)
http_request = [] # We'll store the lines of our incoming request here.

loop do
  socket = server.accept

  while (line = socket.gets) && line.chomp != '' # While the client is connected, and hasn't sent us a blank line yet...
    http_request << line
  end

  # Send response headers
  socket.print "HTTP/1.1 200 OK\r\n" +
               "Content-Type: text/plain\r\n" +
               "Connection: close\r\n" +
               "\r\n"

  # Send response body
  socket.print "Hello world!"
  socket.close
end
需要“套接字”
server=TCPServer.new('localhost',2345)
http_request=[]。#我们将在此处存储传入请求的行。
环道
socket=server.accept
而(line=socket.get)&&line.chomp!=“#虽然客户端已连接,但尚未向我们发送空行。。。

http\u request您不应该使用
get
<代码>获取
尝试读取完整的行(即读取到行分隔符),但不能保证http请求正文以行分隔符结尾


相反,你应该使用
read
-这允许你读取任意数量的数据(正如你提到的,你可以使用content-length头来知道要读取多少数据)

派对已经很晚了,但我目前正在实现我自己的rack app server(为了好玩)

在这里,您可以看到我是如何做到这一点的:

HTTP请求的第一行始终是请求行,基本上类似于
GET/test HTTP/1.1

在请求行之后,直到
\r\n
您得到标题


之后,只需使用从标题解析的
CONTENT\u LENGTH
就可以读取正文(如果PUT/POST请求)。

我相信GET是一个循环,它检索套接字中的所有内容,而不告诉套接字中有多少数据。在我前面的问题中,有人说,
get
方法监听套接字获取数据。如果没有数据可获取,我不知道如何打破
while
循环,而不是继续等待数据。方法是打开的(套接字是
IO
的子类)。特别是请参见和。感谢您的详细解释,但您似乎已经解决了我之前遇到的问题。我能够存储HTTP请求的请求行和头,但我一直无法获取HTTP请求正文(如果有)。当然,但原理是一样的:
gets
在套接字上,当套接字关闭时返回
nil
,客户端在您发送响应之前不会关闭套接字。因此,您需要找到另一种方法来确定是否已收到所有输入。一种方法是定义一些helper方法,并在接收到所有的\u头\u时包含一个
break?&&(不需要身体?| |所有身体?
在循环中<代码>接收到的所有\u头?如果客户端发送了一个空白消息,则返回true