我一直在研究这段代码,由于某种原因服务器无法打开索引文件,我无法理解为什么。我检查了其他人的代码,看起来没有区别。
这是我的代码:
require 'socket'
class Server
def initialize (base, request, server_name, session, charset)
@base = base
@request = request
@charset = charset
@server_name = server_name
@session = session
serve()
end
def serve ()
access_log()
getAddress()
@contentType = getContentType()
@session.print "HTTP/1.1 200 OK\r\nServer: #{@server_name}\r\nContent-Type: #{@contentType}; charset=@{charset}\r\n\r\n"
getFile()
@base = nil
@request = nil
@server_name = nil
@contentType
@session.close
puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
@session = nil
end
def access_log ()
log = File.open(@base + "data/access_log.txt", "w")
log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{@session.peeraddr[2]}:#{@session.peeraddr[1]} #{@request}" unless log == nil
log.close
log = nil
end
def getAddress ()
@src = @request
@src.gsub!(/GET /, '').gsub!(/ HTTP.*/, '')
@src.strip
@src = @base + "root" + @src
@src.gsub!('/', '\\')
end
def getContentType ()
ext = nil
ext = File.extname(@src)
return "text/html" if ext == ".html" or ext == ".htm"
return "text/plain" if ext == ".txt"
return "text/css" if ext == ".css"
return "image/jpeg" if ext == ".jpeg" or ext == ".jpg"
return "image/gif" if ext == ".gif"
return "image/bmp" if ext == ".bmp"
return "text/plain" if ext == ".rb"
return "text/xml" if ext == ".xml"
return "text/xml" if ext == ".xsl"
#return "image/x-icon" if ext == ".ico" or ext == ".icon"
return "text/html"
end
def getFile ()
begin
if !File.exist?(@src)
puts "File: #{@src} could not be found"
if @contentType.include?("image")
file = File.open(@base + "root/server_files/broken_image.png", "r").each do |code|
@session.puts code
end
else
file = File.open(@base + "root/server_files/error404.html", "r").each do |code|
@session.puts code
end
end
else
puts "File #{@src} was opened"
file = File.open(@src, "r").each do |code|
@session.puts code
end
end
ensure
file.close unless file == nil
end
end
end
base = "C:\\Base\\"
server_name = "Some Server"
host = "localhost"
port = 80
charset = "UFT-8"
server = TCPServer.new(host, port)
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n"
loop {
Thread.new(server.accept) do |session|
request = session.gets
puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}"
Server.new(base, request, server_name, session, charset)
end
}
p = gets.chomp
server.close
答案 0 :(得分:1)
代码存在问题。我不知道这些是否直接导致问题,但是有足够的代码味道,以下未经测试的更改可能有所帮助。
不要在Ruby中使用CamelCase方法名称。我们使用snake_case。
require 'socket'
class Server
def initialize(base, request, server_name, session, charset)
@base = base
@request = request
@charset = charset
@server_name = server_name
@session = session
serve()
end
def serve
access_log
get_address()
@content_type = get_content_type()
@session.print "HTTP/1.1 200 OK\r\nServer: #{@server_name}\r\nContent-Type: #{@content_type}; charset=@{charset}\r\n\r\n"
get_file()
@content_type
@session.close
puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
@base = @request = @server_name = @session = nil
end
我不知道你为什么在@content_type
之前的@session.close
行。它不是方法调用,也不会将任何内容返回给服务器或传出数据流。
def access_log
File.open(File.join(@base, "data/access_log.txt"), "w") do |log|
log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{@session.peeraddr[2]}:#{@session.peeraddr[1]} #{@request}"
end
end
Ruby的File.open
需要一个块。当块退出时,文件将自动关闭。 File.join
是构建路径的正确方法。 Ruby知道正确的路径分隔符并将自动使用它们,有助于使代码更具可移植性。
def get_address
src = @request.gsub(/GET /, '').gsub(/ HTTP.*/, '').strip
@src = (@base + "root" + src).gsub('/', '\\')
end
你无缘无故地做了很多gsub!
。将它们链接起来,组合字符串,做最后的gsub
并继续前进。
def get_content_type()
ext = File.extname(@src)
content_type = case ext
when /\.html?/
"text/html"
when ".txt"
"text/plain"
when ".css"
"text/css"
when /\.jpe?g/
"image/jpeg"
when ".gif"
"image/gif"
when ".bmp"
"image/bmp"
when ".rb"
"text/plain"
when /\.x[ms]l/
"text/xml"
else
"text/html"
end
content_type
end
在子例程或方法中有多个returns
令人困惑,所以这会清理它。最后的content_type
将作为方法调用的结果返回。使用case/when
可以为每个when
使用多个测试,从而降低线路噪音。
def get_file()
begin
if !File.exist?(@src)
puts "File: #{@src} could not be found"
if @content_type["image"]
File.open(File.join(@base, "root", "server_files", "broken_image.png"), "rb") do |image|
@session.puts image.read
end
else
File.foreach(File.join(@base, "root", "server_files", "error404.html")) do |li|
@session.puts li
end
end
else
puts "File #{@src} was opened"
File.foreach(@src) do |li|
@session.puts li
end
end
rescue Exception => e
puts e.message
end
end
如果要读取二进制文件,例如“broken_image.png”,请始终以二进制模式打开它:"rb"
。否则,Ruby会认为将行结尾转换为操作系统的本机格式是可以的,这会破坏数据。此外,再次使用File方法的块形式,以便它们自动关闭。并且,使用File.join
来实现可移植性。当您阅读文本文件时,请使用File.foreach
逐行阅读,除非您知道它将适合可用内存; “啜饮”你的文件是不好的形式,因为它不可扩展。
end
base = "C:/Base/"
server_name = "Some Server"
host = "localhost"
port = 80
charset = "UFT-8"
server = TCPServer.new(host, port)
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n"
loop {
Thread.new(server.accept) do |session|
request = session.gets
puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}"
Server.new(base, request, server_name, session, charset)
end
}
p = gets.chomp
server.close