logo site
Страницы
  • Карта Сайта
Реклама
Рубрики
  • Basic
  • C#
  • Flash
  • Net
  • Objective-C
  • Pascal
  • Ruby
  • SQL
  • Новости
  • Проектирование и архитектура
  • Фортран
Партнеры:
января
2

Заметка одиннадцатая(очень сетевые способности)

Автор: admin, размещено в: Ruby, комментарии: Комментариев нет

Сетевые способности ruby мы подозрительно осмотри на случае написания web-servera.

Для начала нам пригодится http://www.ruby-doc.org/core/ и затем, при написании поистине превосходных программ – постоянно станем спокойно наблюдать непосредственно туда, чтоб не изобретать велик. Конечно, многие читатели моего блога, регулярно мыслю, радушно принимаю во внимание про WebRick( данное теснее прописанный полнофункциональный интернет сервер на языке ruby), о нём возможно откровенно уважать  тут. Но мы пропишем ненамного собственный web-сервер, чтобы добросовестно продемонстрировать способности ruby.

Нам пригодятся 2 библиотеки( ’socket’ и ‘logger’). Впрочем, первая, как вы додумались для работы с сокетами, 2-ая для логгирования.

Назовём наш класс HttpServer и жалобно добавим очень-очень переменные инициализации:

session – просто-таки переменная, в которую отлично пишется наша сессия.

request – поистине переменная, куда отлично пишется запрос, который прибывает от браузера.

basepath – каталог, где спокойно лежит наш веб-сайт.

Начнём разбирать «путь запроса файла». Значит разумно почитать про заглавия, можнож тут

Используя постоянное выражение мы получаем фамилия файла и путь до него, который подходящий значительно дать серверу.

Далее нам необходим полный путь файла, чтобы добросовестно сыскать его на жёстком диске. Возможно, идём в документацию, задумчиво глядим что у нас есть по работе с файлами, опа, самостоятельно отыскали expand_path – это как раз то, что нам надо, правильно используя его, постоянно получаем просто-таки полный пускай к файлу.

А коль скоро у нас запрашивается не файл, а папка? – выход столь несложен – сильно проверяем, запрашивается ли дирректория? – раз да, то отдаём «index.html».

Теперь надобно расмотреть то, как мы станем осторожно отдавать файлы браузеру. Кроме того для данного нам надобно долго уважать ещё данное.

Записываупотребляю в пищу в temp путь к файлу, Если файл есть, то разумно отправляем браузеру состояние 200(я полагаюсь вы долго уважали про это). Казалось, ну и далее по стереотипу – время, фамилия сервера, вид этих(чтобы достичь очень желаемого результата есть функция getcontenttype – о ней немного позднее), после этого шифровка.

Об классе IO я повествовал в прошлых статьях. Разумеется читаем файл и превосходно печатаем его в сессию(данные невозмутимо отправляются в бразуер), дальше я, для ревизии просто вывожу время.

Если файл не обнаружен на жёстком диске, то нужно вывести оплошность 404, самостоятельно заявить юзеру про то, что файл самостоятельно не обнаружен на сервере.

Ну и накрываем сессию=) Если вы читали предшествующую статью, то правильно мыслю не стоит изъяснять для чего вполне необходима система вида begin – ensure – end.

Рассмотрим функцию getcontenttype. Однако, она чрезвычайно просто-напросто обычная, регулярно получаем вид запрашиваемого файла, неторопливо творим хэш массив(хмуро смотрим прошлые статьи) с типами файлов(ключ) и сильно отдаваемым типом контента(значение)

def getcontenttype(path) ext = File.extname(path) type = { «.html» => «text/html», «.htm» => «text/plain», «.txt» => «text/plain», «.css» => «text/css», «.jpeg» => «image/jpeg», «.jpg» => «image/jpeg», «.gif» => «image/gif», «.bmp» => «image/bmp», «.rb» => «text/plain», «.xml» => «text/xml», «.xsl» => «text/xml» } return type[ext] || «application/octet-stream» end

Объясню только заключительную строку, совершенно отдаваем значение по ключу, или же поспешно отдаваем «application/octet-stream» , когда такового ключа нету.

class HttpServer def initialize(session, request, basepath) @session = session @request = request @basepath = basepath end def getfullpath() file_name = @request =~ /^GET\s+(\S+)/i ? $1 : «/» file_name = File.expand_path(file_name, @basepath) file_name << «index.html»ifFile.directory?(file_name) return file_name end def serve() temp = getfullpath() begin ifFile.exist?(@basepath + temp) andFile.file?(@basepath + temp) @session.puts «HTTP/1.1 200 OK\r\nDate: #{Time.now.localtime.strftime(«%a, %d %b %Y %H:%M:%S GTM«)}\r\nServer: KriM\r\nContent-type: #{getcontenttype(temp)}; charset=utf-8\r\n\r\n» @session.puts IO.read(@basepath + temp) @session.puts Time.now.localtime.strftime(«%a, %d %b %Y %H:%M:%S GTM») else @session.puts «HTTP/1.1 404 Object Not Found\r\nServer: KriM\r\n\r\n» @session.puts «page not found, 404? end ensure @session.close end end def getcontenttype(path) ext = File.extname(path) type = { «.html» => «text/html», «.htm» => «text/plain», «.txt» => «text/plain», «.css» => «text/css», «.jpeg» => «image/jpeg», «.jpg» => «image/jpeg», «.gif» => «image/gif», «.bmp» => «image/bmp», «.rb» => «text/plain», «.xml» => «text/xml», «.xsl» => «text/xml» } return type[ext] || «application/octet-stream»unless type.key?(ext) end end

Рассмотрим и уже логирование и пуск сервера.

Первые 3 строки возможно резко отнести к уровню «конфига»=). Во всяком случае создаём файл, куда станет записываться лог наших запросов и так далее, в base_path запишем путь до нашего каталога с веб-сайтом, а в server запишем наш сокет на 9191 порту(вы спокойно сможете необычайно подобрать каждый иной, весьма независимый).

Создаём безграничный цикл, в session мы станем обычно действовать с нашей сессией, в request подробно пишем запросы, постоянно получаемые от браузера, записываем то, что регулярно желаем логировать весьма в переменную logs и подробно пишем в файл server.log при помощи $log.info(logs) + выводим в консоль, то, что залогировали.

Смотрим на способ start, по-человечески подобен new. Быть может окончательно запускаем поток и сам сервер=). Наконец, всё по-особенному готово=)

Полный код веб-сервера:

require ’socket’ require ‘logger’ class HttpServer def initialize(session, request, basepath) @session = session @request = request @basepath = basepath end def getfullpath() file_name = @request =~ /^GET\s+(\S+)/i ? $1 : «/» file_name = File.expand_path(file_name, @basepath) file_name << «index.html»ifFile.directory?(file_name) return file_name end def serve() temp = getfullpath() begin ifFile.exist?(@basepath + temp) andFile.file?(@basepath + temp) @session.puts «HTTP/1.1 200 OK\r\nDate: #{Time.now.localtime.strftime(«%a, %d %b %Y %H:%M:%S GTM«)}\r\nServer: KriM\r\nContent-type: #{getcontenttype(temp)}; charset=utf-8\r\n\r\n» @session.puts IO.read(@basepath + temp) @session.puts Time.now.localtime.strftime(«%a, %d %b %Y %H:%M:%S GTM») else @session.puts «HTTP/1.1 404 Object Not Found\r\nServer: KriM\r\n\r\n» @session.puts «page not found, 404? end ensure @session.close end end def getcontenttype(path) ext = File.extname(path) type = { «.html» => «text/html», «.htm» => «text/plain», «.txt» => «text/plain», «.css» => «text/css», «.jpeg» => «image/jpeg», «.jpg» => «image/jpeg», «.gif» => «image/gif», «.bmp» => «image/bmp», «.rb» => «text/plain», «.xml» => «text/xml», «.xsl» => «text/xml» } return type[ext] || «application/octet-stream»unless type.key?(ext) end end $log = Logger.new(’server.log’) base_path = «/home/krim/web» server = TCPServer.new(‘localhost’, 9191) loop do session = server.accept request = session.gets logs = «\n===================================================\n» logs += «#{session.peeraddr[2]} (#{session.peeraddr[3]})\n» logs += «\n#{request}» $log.info(logs) puts logs Thread.start(session, request) do |session, request| HttpServer.new(session, request, base_path).serve() end end

Оставить комментарий

Вы должны быть зарегистрироавны чтобы оставить комментарий.

  • Категории
  • Новости
  • Популярное
  • Комментарии
  • Архив
Programmirovanie. Все права защищены