Как контролировать несколько групп многоадресной рассылки одновременно

В настоящее время я использую Ruby 1.8.7 для разработки Linux-версии инструмента для Windows, который проверяет многоадресные данные на двух интерфейсах на основе настроенных пользователем многоадресных групп и портов.

У меня была предыдущая проблема, когда я не знал, как слушать несколько многоадресных каналов, но это было решено с помощью предыдущего вопроса.

Это привело к следующей проблеме. Мне нужно слушать несколько многоадресных групп и:

  • Определите, были ли получены какие-либо данные по каждой из конкретных групп, и сообщите, какие из них имеют данные, а какие нет.

  • Слушайте данные в течение настраиваемого пользователем периода времени ожидания на всех каналах одновременно.

Я пытаюсь заставить это работать в отдельном фрагменте кода, где многоадресные группы, порты и интерфейсы жестко закодированы, как только я разберусь и пойму, я перенесу его в свою основную программу, где пользовательский ввод и проверка уже завершены . Я обновил свой простой программный код, и теперь он выглядит так:

#!/usr/bin/ruby

require 'socket'
require 'ipaddr'
require 'timeout'

MCAST_GROUP_A
{
  :addr1 => '233.54.12.111',
  :addr2 => '233.86.230.111',
  :port => 26477,
  :bindaddr => '172.31.230.156'
}

MCAST_GROUP_B = 
{
  :addr => '233.54.12.111',
  :port => 18170,
  :bindaddr => '172.31.230.156'
}

ipA1 = IPAddr.new(MCAST_GROUP_A[:addr1]).hton + IPAddr.new(MCAST_GROUP_A[:bindaddr]).hton
ipA2 = IPAddr.new(MCAST_GROUP_A[:addr2]).hton + IPAddr.new(MCAST_GROUP_A[:bindaddr]).hton
ipB = IPAddr.new(MCAST_GROUP_B[:addr]).hton + IPAddr.new(MCAST_GROUP_B[:bindaddr]).hton

begin
  sockA = UDPSocket.open
  sockB = UDPSocket.open

  sockA.bind Socket::INADDR_ANY, MCAST_GROUP_A[:port]
  sockB.bind Socket::INADDR_ANY, MCAST_GROUP_B[:port]

  sockA.setsockopt Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ipA1
  sockA.setsockopt Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ipA2
  sockB.setsockopt Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ipB

  timeoutSeconds = 10
  Timeout.timeout(timeoutSeconds) do 
    msg1, info1 = sockA.recvfrom(1024)
    msg2, info2 = sockB.recvfrom(1024)
    #puts "MSG: #{msg} from #{info[2]} (#{info[3]})/#{info[1]} len #{msg.size}"
    puts "MSG: <garbled> from #{info1[2]} (#{info1[3]})/#{info1[1]} len #{msg1.size}"
    puts "MSG: <garbled> from #{info2[2]} (#{info2[3]})/#{info2[1]} len #{msg2.size}"
  end
  rescue Timeout::Error
    puts "Nothing received connection timedout\n"
ensure
  sockA.close
  sockB.close
end

Но это привело к проблеме, заключающейся в том, что он сообщает, что ничего не получено, потому что данных в сокете B нет.

Я понимаю, что причина этого в том, что второй recvfrom истекает, и из-за этого мы оказываемся в спасательной части кода. Но поскольку это моя первая программа на Ruby, и я все еще изучаю ее, я не уверен, что делать, чтобы ее решить.

Короче мне нужно понять:

  • Как определить, какие данные канала были получены для sockA, поскольку в этом сокете есть 2 группы многоадресной рассылки

  • Как одновременно отслеживать настраиваемое количество групп многоадресной рассылки для данных и не допустить, чтобы одна ошибка при получении данных приводила к выводу неправильной ошибки


person Glen    schedule 02.07.2015    source источник


Ответы (1)


Для одновременного мониторинга нескольких сокетов вы используете функцию select. Этот вопрос дает пример того, как это делается в Ruby.

По крайней мере, в C можно получить адрес назначения входящего пакета, используя параметр сокета IP_PKTINFO и функцию recvfrom, однако не похоже, что API-интерфейсы Ruby предоставляют эту функциональность.

person dbush    schedule 02.07.2015