-1

我一直在处理这段代码,由于某种原因,服务器无法打开索引文件,我不明白为什么。我检查了其他人的代码,看起来没有区别。

这是我的代码:

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
4

1 回答 1

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'sFile.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,因此将其清理干净。finalcontent_type将作为方法调用的结果返回。Usingcase/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

代码更改位于:https ://gist.github.com/anonymous/6515451

于 2013-09-10T20:31:27.043 回答