Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

draw_dice(get_random_numbers(5, 1, 6))

Здесь мы воспользовались классом

Net::НТТР
для прямого взаимодействия с Web-сервером. Считайте, что эта программа — узкоспециализированный браузер. Мы формируем URL и пытаемся установить соединение; когда оно будет установлено, мы получаем ответ, возможно, содержащий некие данные. Если код ответа показывает, что ошибок не было, то можно разобрать полученные данные. Предполагается, что исключения будут обработаны вызывающей программой.

Посмотрим на вариацию этой идеи. Что если вы захотели бы применить случайные числа в каком-нибудь приложении? Поскольку обслуживающая программа на стороне сервера позволяет указать количество возвращаемых чисел, то было бы логично сохранить их в буфере. Учитывая, что при обращении к удаленному серверу задержки неизбежны, следует сразу заполнить буфер во избежание лишних запросов по сети.

В листинге 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 км от вас.

Поделиться:
Популярные книги

Русич. Бей первым

Поселягин Владимир Геннадьевич
1. Русич
Фантастика:
фэнтези
5.25
рейтинг книги
Русич. Бей первым

Идеальный мир для Лекаря

Сапфир Олег
1. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря

Моров. Том 3

Кощеев Владимир
2. Моров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Моров. Том 3

Черный Маг Императора 4

Герда Александр
4. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 4

Эволюционер из трущоб. Том 3

Панарин Антон
3. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
6.00
рейтинг книги
Эволюционер из трущоб. Том 3

Вперед в прошлое 5

Ратманов Денис
5. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 5

Изменяющий-Механик. Компиляция. Книги 1-18

Усманов Хайдарали
Собрание сочинений
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Изменяющий-Механик. Компиляция. Книги 1-18

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

Потомок бога

Решетов Евгений Валерьевич
1. Локки
Фантастика:
попаданцы
альтернативная история
аниме
сказочная фантастика
5.00
рейтинг книги
Потомок бога

Имя нам Легион. Том 13

Дорничев Дмитрий
13. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 13

Имперец. Том 5

Романов Михаил Яковлевич
4. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Имперец. Том 5

Месть Паладина

Юллем Евгений
5. Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Месть Паладина

Сильнейший Столп Империи. Книга 5

Ермоленков Алексей
5. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 5

Искатель 7

Шиленко Сергей
7. Валинор
Фантастика:
рпг
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Искатель 7