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

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

Жанры

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

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

Ворон

Смолл Бертрис
Любовные романы:
исторические любовные романы
8.79
рейтинг книги
Ворон

Валгалла

Азимов Айзек
Фантастика:
научная фантастика
7.00
рейтинг книги
Валгалла

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

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

Завещание предков

Стрелков Владислав Валентинович
Приключения:
исторические приключения
6.14
рейтинг книги
Завещание предков

Предсказание

Катри Клинг
Фантастика:
фэнтези
5.00
рейтинг книги
Предсказание

Отверженный III: Вызов

Опсокополос Алексис
3. Отверженный
Фантастика:
фэнтези
альтернативная история
7.75
рейтинг книги
Отверженный III: Вызов

Тузы за границей

Мартин Джордж Р.Р.
4. Дикие карты
Фантастика:
научная фантастика
7.14
рейтинг книги
Тузы за границей

Империя страха

Колычев Владимир Григорьевич
Детективы:
криминальные детективы
6.40
рейтинг книги
Империя страха

Первопроходцы

Полевой Борис Николаевич
638. Жизнь замечательных людей
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Первопроходцы

Любовь - только слово

Зиммель Йоханнес Марио
Проза:
классическая проза
5.00
рейтинг книги
Любовь - только слово

Триптих. Одиночество в Сети

Вишневский Януш Леон
Проза:
современная проза
8.46
рейтинг книги
Триптих. Одиночество в Сети

Егерь. Столичный гамбит

Скиба Николай
4. Зверолов
Фантастика:
рпг
уся
фэнтези
фантастика: прочее
попаданцы
6.67
рейтинг книги
Егерь. Столичный гамбит

Точка Бифуркации XI

Смит Дейлор
11. ТБ
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Точка Бифуркации XI

Немец

Костин Юрий Алексеевич
Проза:
военная проза
6.83
рейтинг книги
Немец