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

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

Жанры

Программирование на языке 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 км от вас.

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

Хозяин оков VI

Матисов Павел
6. Хозяин Оков
Фантастика:
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Хозяин оков VI

Черный дембель. Часть 1

Федин Андрей Анатольевич
1. Черный дембель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черный дембель. Часть 1

Золото Советского Союза: назад в 1975. Книга 2

Майоров Сергей
2. Золото Советского Союза
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Золото Советского Союза: назад в 1975. Книга 2

Орден Архитекторов 12

Винокуров Юрий
12. Орден Архитекторов
Фантастика:
фэнтези
5.00
рейтинг книги
Орден Архитекторов 12

Я все еще барон

Дрейк Сириус
4. Дорогой барон!
Фантастика:
боевая фантастика
5.00
рейтинг книги
Я все еще барон

Глава рода

Шелег Дмитрий Витальевич
5. Живой лёд
Фантастика:
боевая фантастика
6.55
рейтинг книги
Глава рода

Наследник старого рода

Шелег Дмитрий Витальевич
1. Живой лёд
Фантастика:
фэнтези
8.19
рейтинг книги
Наследник старого рода

Телохранитель Генсека. Том 1

Алмазный Петр
1. Медведев
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Телохранитель Генсека. Том 1

Моя простая курортная жизнь

Блум М.
1. Моя простая курортная жизнь
Проза:
современная проза
5.00
рейтинг книги
Моя простая курортная жизнь

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

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

Последний Паладин. Том 9

Саваровский Роман
9. Путь Паладина
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Последний Паладин. Том 9

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Треск штанов

Ланцов Михаил Алексеевич
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Треск штанов

Локки 9. Потомок бога

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