- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование на языке Ruby - Хэл Фултон
Шрифт:
Интервал:
Закладка:
Посмотрим на вариацию этой идеи. Что если вы захотели бы применить случайные числа в каком-нибудь приложении? Поскольку обслуживающая программа на стороне сервера позволяет указать количество возвращаемых чисел, то было бы логично сохранить их в буфере. Учитывая, что при обращении к удаленному серверу задержки неизбежны, следует сразу заполнить буфер во избежание лишних запросов по сети.
В листинге 18.5 эта мысль реализована. Буфер заполняется отдельным потоком и совместно используется всеми экземплярами класса. Размер буфера и «нижняя отметка» (@slack) настраиваются; какие значения задать в реальной программе, зависит от величины задержки при обращении к серверу и от того, как часто приложение выбирает случайное число из буфера.
Листинг 18.5. Генератор случайных чисел с буферизациейrequire "net/http"
require "thread"
class TrueRandom
def initialize(min=nil,max=nil,buff=nil,slack=nil)
@buffer = []
@site = "www.random.org"
if ! defined? @init_flag
# Принять умолчания, если они не были заданы явно И
# это первый созданный экземпляр класса...
@min = min || 0
@max = max || 1
@bufsize = buff || 1000
@slacksize = slack || 300
@mutex = Mutex.new
@thread = Thread.new { fillbuffer }
@init_flag = TRUE # Значение может быть любым.
else
@min = min || @min
@max = max || @max
@bufsize = buff || @bufsize
@slacksize = slack || @slacksize
end
@url = "/cgi-bin/randnum" +
"?num=#@bufsize&min=#@min&max=#@max&col=1"
end
def fillbuffer
h = Net::HTTP.new(@site, 80)
resp, data = h.get(@url, nil)
@buffer += data.split
end
def rand
num = nil
@mutex.synchronize { num = @buffer.shift }
if @buffer.size < @slacksize
if ! @thread.alive?
@thread = Thread.new { fillbuffer }
end
end
if num == nil
if @thread.alive?
@thread.join
else
@thread = Thread.new { fillbuffer }
@thread.join
end
@mutex.synchronize { num = @buffer.shift }
end
num.to_i
end
end
t = TrueRandom.new(1,6,1000,300)
count = {1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0}
10000.times do |n|
x = t.rand
count[x] += 1
end
p count
# При одном прогоне:
# {4=>1692, 5=>1677, 1=>1678, 6=>1635, 2=>1626, 3=>1692}
18.2.2. Запрос к официальному серверу времени
Как мы и обещали, приведем программу для обращения к NTP-серверу в сети (NTP — Network Time Protocol (синхронизирующий сетевой протокол). Показанный ниже код заимствован с небольшой переработкой у Дэйва Томаса.
require "net/telnet"
timeserver = "www.fakedomain.org"
local = Time.now.strftime("%H:%M:%S")
tn = Net::Telnet.new("Host" => timeserver,
"Port" => "time",
"Timeout" => 60,
"Telnetmode" => false)
msg = tn.recv(4).unpack('N')[0]
# Преобразовать смещение от точки отсчета
remote = Time.at(msg — 2208988800).strftime("%H:%M:%S")
puts "Местное : #{local}"
puts "Удаленное : #{remote}"
Мы устанавливаем соединение и получаем четыре байта. Они представляют 32-разрядное число в сетевом (тупоконечном) порядке байтов. Это число преобразуется в понятную форму, а затем — из смещения от точки отсчета в объект Time.
Мы не указали имя реального сервера. Дело в том, что его полезность часто зависит от того, где вы находитесь. Кроме того, многие серверы ограничивают доступ, так что для запроса вы должны получить разрешение или хотя бы уведомить владельца. Поисковая машина поможет найти открытый NTP-сервер в радиусе 1000 км от вас.
18.2.3. Взаимодействие с РОР-сервером
Многие серверы электронной почты пользуются почтовым протоколом (Post Office Protocol — POP). Имеющийся в Ruby класс POP3 позволяет просматривать заголовки и тела всех сообщений, хранящихся для вас на сервере, и обрабатывать их как вы сочтете нужным. После обработки сообщения можно удалить.
Для создания объекта класса Net::POP3 нужно указать доменное имя или IP-адрес сервера; номер порта по умолчанию равен 110. Соединение устанавливается только после вызова метода start (которому передается имя и пароль пользователя).
Вызов метода mails созданного объекта возвращает массив объектов класса POPMail. (Имеется также итератор each для перебора этих объектов.)
Объект POPMail соответствует одному почтовому сообщению. Метод header получает заголовки сообщения, а метод all — заголовки и тело (у метода all, как мы вскоре увидим, есть и другие применения).
Фрагмент кода стоит тысячи слов. Вот пример обращения к серверу с после дующей распечаткой темы каждого сообщения:
require "net/pop"
pop = Net::POP3.new("pop.fakedomain.org")
pop.start("gandalf", "mellon") # Имя и пароль пользователя.
pop.mails.each do |msg|
puts msg.header.grep /^Subject: /
end
Метод delete удаляет сообщение с сервера. (Некоторые серверы требуют, чтобы POP-соединение было закрыто методом finish, только тогда результат удаления становится необратимым.) Вот простейший пример фильтра спама:
require "net/pop"
pop = Net::POP3.new("pop.fakedomain.org")
pop.start("gandalf", "mellon") # Имя и пароль пользователя.
pop.mails.each do |msg|
if msg.all =~ /.*make money fast.*/
msg.delete
end
end
pop.finish
Отметим, что при вызове метода start можно также задавать блок. По аналогии с методом File.open в этом случае открывается соединение, исполняется блок, а затем соединение закрывается.
Метод all также можно вызывать с блоком. В блоке просто перебираются все строки сообщения, как если бы мы вызвали итератор each для строки, возвращенной методом all.
# Напечатать все строки в обратном порядке... полезная штука!
msg.all { |line| print line.reverse }
# To же самое...
msg.all.each { |line| print line.reverse }
Методу all можно также передать объект. В таком случае для каждой строчки (line) в полученной строке (string) будет вызван оператор конкатенации (<<). Поскольку в различных объектах он может быть определен по-разному, в результате такого обращения возможны самые разные действия:
arr = [] # Пустой массив.
str = "Mail: " # String.
out = $stdout # Объект IO.
msg.all(arr) # Построить массив строчек.
msg.all(str) # Конкатенировать с str.
msg.all(out) # Вывести на stdout.
Наконец, покажем еще, как вернуть только тело сообщения, игнорируя все заголовки.
module Net
class POPMail
def body
# Пропустить байты заголовка
self.all[self.header.size..-1]
end
end
end
Если вы предпочитаете протокол IMAP, а не POP3, обратитесь к разделу 18.2.5
18.2.4. Отправка почты по протоколу SMTP
Это понял бы и пятилетний ребенок. Дайте мне пятилетнего ребенка.
Гроучо МарксНазвание «простой протокол электронной почты» (Simple Mail Transfer Protocol — SMTP) не вполне правильно. Если он и «простой», то только по сравнению с более сложными протоколами.
Конечно, библиотека smtp.rb скрывает от программиста большую часть деталей протокола. Но, на наш взгляд, эта библиотека интуитивно не вполне очевидна и, пожалуй, слишком сложна (надеемся, что в будущем это изменится). В этом разделе мы приведем несколько примеров, чтобы помочь вам освоиться.
В классе Net::SMTP есть два метода класса: new и start. Метод new принимает два параметра: имя сервера (по умолчанию localhost) и номер порта (по умолчанию 25).
Метод start принимает следующие параметры:
• server — доменное имя или IP-адрес SMTP-сервера; по умолчанию это "localhost";
• port — номер порта, по умолчанию 25;
• domain — доменное имя отправителя, по умолчанию ENV["HOSTNAME"];
• account — имя пользователя, по умолчанию nil;
• password — пароль, по умолчанию nil;
• authtype — тип авторизации, по умолчанию :cram_md5.
Обычно большую часть этих параметров можно не задавать.
Если метод start вызывается «нормально» (без блока), то он возвращает объект класса SMTP. Если же блок задан, то этот объект передается прямо в блок.
У объекта SMTP есть метод экземпляра sendmail, который обычно и занимается всеми деталями отправки сообщения. Он принимает три параметра:

