print line[(v-1)*DIE_WIDTH, DIE_WIDTH]

   print ' '

  end

  puts

 end

end

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 (синхронизирующий сетевой протокол). Показанный ниже код заимствован с небольшой

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату