Aus*_*yde 8 ruby sockets http tcpserver
对于学校作业,我试图使用Ruby和套接字库创建一个简单的HTTP服务器.
现在,我可以通过一个简单的问候来响应任何连接:
require 'socket'
server = TCPServer.open 2000
puts "Listening on port 2000"
loop {
client = server.accept()
resp = "Hello?"
headers = ["HTTP/1.1 200 OK",
"Date: Tue, 14 Dec 2010 10:48:45 GMT",
"Server: Ruby",
"Content-Type: text/html; charset=iso-8859-1",
"Content-Length: #{resp.length}\r\n\r\n"].join("\r\n")
client.puts headers
client.puts resp
client.close
}
Run Code Online (Sandbox Code Playgroud)
这按预期工作.但是,当我让服务器告诉我谁刚刚连接
puts "Client: #{client.addr[2]}"
Run Code Online (Sandbox Code Playgroud)
并使用Chromium(浏览器)连接localhost:2000/(只需一次),我得到:
Client: 127.0.0.1
Client: 127.0.0.1
Client: 127.0.0.1
Client: 127.0.0.1
Run Code Online (Sandbox Code Playgroud)
我假设这是Chromium请求辅助文件,favicon.ico而不是我的脚本做一些奇怪的事情,所以我想调查传入的请求.我换了resp = "Hello?"一行
resp = client.read()
Run Code Online (Sandbox Code Playgroud)
并重新启动服务器.我对Chromium的请求表示不满,而不是立即回来,它只是挂了.同时,我Client: 127.0.0.1在服务器输出中得到了输出.我点击了Chromium中的"停止"按钮,然后服务器崩溃了
server.rb:16:in `write': Broken pipe (Errno::EPIPE)
from server.rb:16:in `puts'
from server.rb:16:in `block in <main>'
from server.rb:6:in `loop'
from server.rb:6:in `<main>'
Run Code Online (Sandbox Code Playgroud)
显然,我做错了,因为预期的行为是将响应请求作为响应发回.
我错过了什么?
And*_*dev 20
我真的不知道chrome和四个连接,但我会尝试回答你关于如何正确阅读请求的问题.
首先,IO#read在这种情况下不起作用.根据文档,read没有任何参数读取,直到它遇到EOF,但没有发生这种情况.套接字是一个循环流,您将无法使用该方法读取整个消息,因为套接字没有"完整"消息.您可以使用带有整数的读取,例如read(100)或类似的东西,但无论如何都会在某些时候阻塞.
基本上,读取套接字与读取文件非常不同.套接字是异步更新的,完全独立于您尝试读取它的时间.如果您请求10个字节,那么在代码中此时,可能只有5个字节可用.通过阻塞 IO,read(10)呼叫将挂起并等待5个字节可用,或者直到连接关闭.这意味着,如果您尝试重复读取10个字节的数据包,在某些时候,它仍会挂起.另一种读取套接字的方法是使用非阻塞IO,但这在你的情况下并不是很重要,而且它本身就是一个很长的话题.
这是一个如何使用阻塞IO访问数据的示例:
loop {
client = server.accept
while line = client.gets
puts line.chomp
break if line =~ /^\s*$/
end
# rest of loop ...
}
Run Code Online (Sandbox Code Playgroud)
该gets方法尝试从套接字读取,直到遇到换行符.对于HTTP请求,这将在某个时刻发生,因此即使整个消息是逐个传输的,也gets应该从输出返回一行.line.chomp如果它们存在,那么这个电话会切断最后的新行.如果读取的行是空的,那意味着HTTP头已经被转移,我们可以安全地打破循环(while当然,你可以把它放在条件中).请求将被转储到已启动服务器的控制台.如果你真的想把它发回浏览器,想法是一样的,你只需要以不同的方式处理这些行:
loop {
client = server.accept
lines = []
while line = client.gets and line !~ /^\s*$/
lines << line.chomp
end
resp = lines.join("<br />")
headers = ["http/1.1 200 ok",
"date: tue, 14 dec 2010 10:48:45 gmt",
"server: ruby",
"content-type: text/html; charset=iso-8859-1",
"content-length: #{resp.length}\r\n\r\n"].join("\r\n")
client.puts headers # send the time to the client
client.puts resp
client.close
}
Run Code Online (Sandbox Code Playgroud)
对于损坏的管道,发生该错误是因为浏览器在read尝试访问数据时强行断开连接.
| 归档时间: |
|
| 查看次数: |
10061 次 |
| 最近记录: |