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

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

Жанры

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

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

Император Пограничья 10

Астахов Евгений Евгеньевич
10. Император Пограничья
Фантастика:
городское фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 10

Двойник короля 16

Скабер Артемий
16. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 16

Бояръ-Аниме. Газлайтер. Том 33

Володин Григорий Григорьевич
33. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 33

Кодекс Охотника. Книга XIII

Винокуров Юрий
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XIII

Охотник за головами

Вайс Александр
1. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Охотник за головами

Отмороженный 12.0

Гарцевич Евгений Александрович
12. Отмороженный
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Отмороженный 12.0

Кодекс Охотника. Книга XXXIV

Винокуров Юрий
34. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIV

Как я строил магическую империю 11

Зубов Константин
11. Как я строил магическую империю
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Как я строил магическую империю 11

Цикл "Идеальный мир для Лекаря". Компиляция. Книги 1-30

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

Академия

Сай Ярослав
2. Медорфенов
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Академия

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

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

Нелюдь

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

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

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

Ярар. Начало

Грехов Тимофей
1. Ярар
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ярар. Начало