|
|
|
| Здравствуйте.
Есть ряд коммутаторов, на которые заходит скрипт по SNMP и получает некую полезную информацию. Порой коммутаторы выходят из строя и заменяются на новые, с новым IP, таким образом часть IP адресов из подсети которая назначена коммутаторам просто недоступны. Скрипт, когда встречает такой IP, берёт тайм-аут в секунду, за тем понимает, что коммутатор с таким IP не доступен и двигается дальше по диапазону IP адресов обходя все остальные коммутаторы.
Необходимо нанести превентивный удар по недоступным IP исключив их из списка IP на которые заходит скрипт, чтоб он зря время не терял (секунда там секунда здесь и в результате несколько минут бесполезного ожидания).
Вот код:
<?php
// Задаём диапазон IP адресов (подсеть 192.168.25.0/19)
$network_25 = array('start' => ip2long('192.168.25.0'), 'end' => ip2long('192.168.31.254'));
// Инициируем массив, в котором будем хранить IP активных коммутаторов
$address_ranges = array();
// В цикле обходим все коммутаторы и выясняем доступны ли они
for($i = $network_25['start']; $i <= $network_25['end']; $i++)
{
// Преобразуем число обратно в IP
$ip_dlink = long2ip($i);
// Проверяем доступность коммутатора
$fp = @fsockopen($ip_dlink, '23', $errno, $errstr, 1);
if (!$fp)
{
// Здесь код который делает все хорошо
}
}
?>
|
Необходимо массив $address_ranges с помощью кода "// Здесь код который делает все хорошо" привести к виду:
$address_ranges = array(
array('start' => ip2long('192.168.25.145'), 'end' => ip2long('192.168.25.146')),
array('start' => ip2long('192.168.25.150'), 'end' => ip2long('192.168.25.219')),
array('start' => ip2long('192.168.25.221'), 'end' => ip2long('192.168.25.254')),
array('start' => ip2long('192.168.26.1'), 'end' => ip2long('192.168.26.254')),
array('start' => ip2long('192.168.27.1'), 'end' => ip2long('192.168.27.254')),
array('start' => ip2long('192.168.28.1'), 'end' => ip2long('192.168.28.239')),
array('start' => ip2long('192.168.29.241'), 'end' => ip2long('192.168.29.254'))
);
|
Есть идеи, как такое провернуть?
Решить задачу в лоб в принципе, с начала, кажется не сложно. Необходимо выставить некий флаг, который показывает, что сейчас код "// Здесь код который делает все хорошо" натыкается на недоступные IP (ну ещё бы 192.168.25.0 уж точно не доступен) и как только код "// Здесь код который делает все хорошо" наткнётся на доступный IP он должен сделать:
$address_ranges[$i]['start'] = $ip_dlink
|
и выставить флаг в положение я работаю с доступными IP, затем, как только код наткнётся на недоступный IP он должен сделать:
$address_ranges[$i]['end'] = $ip_dlink
|
и выставить флаг в положение я работаю с не доступными IP...
И вот тут начинаются проблемы $address_ranges[$i]['end'] будет присвоен IP недоступного коммутатора, а на самом деле надо присвоить предыдущий IP...
В общем чувствую, что решение где-то рядом совсем, а я его не вижу. Ребята разбирающиеся в математике наверняка легко решат подобную задачу, но вот у меня с математикой проблемы небольшие.
Подтолкните к правильному решению пожалуйста. | |
|
|
|
|
|
|
|
для: Proton
(06.03.2013 в 20:20)
| | Ночь прошла и до меня дошло наконец как это должно выглядеть.
Мне нужен один массив содержащий только валидные IP. Его легко сгенерировать и легко обойти с помощью foreach. Это так же позволит мне избавиться от вложенного цикла. | |
|
|
|
|
|
|
|
для: Proton
(08.03.2013 в 09:31)
| | Нифига себе!!! Время выполнения скрипта: 2.77 секунд
Знал, что время выполнения сократиться, но чтоб так!
Просто по сгенерированному массиву заведомо доступных коммутаторов скрипт проходится, вот и всё. | |
|
|
|
|
|
|
|
для: Proton
(08.03.2013 в 11:44)
| | можно еще попробовать пинговать эти IP вдруг какой-то отвалился, и можно сделать unset()
при доступных IP вроде время особо не должно увеличиться, потеря времени как раз составляла на недоступных IP
ping с теми параметрами которые я указал в скрипте, в два раза быстрее чем проверка через
$fp = @fsockopen($ip_dlink, '23', $errno, $errstr, 1);
|
| |
|
|
|
|
|
|
|
для: Valick
(08.03.2013 в 12:37)
| | unset() тоже хорошая. Пожалуй воспользуюсь ею.
Только вот не хочется внешние программы запускать. Пока использую вот такую конструкцию, чтоб проверять можно коннектиться к коммутатору или нет:
<?php
function test_dlink_connection($ip_dlink)
{
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_block($socket);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>0, 'usec'=>30000));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>0, 'usec'=>30000));
$test = @socket_connect($socket, $ip_dlink, 23);
socket_close($socket);
return $test;
}
?>
|
Вроде работает... | |
|
|
|
|
|
|
|
для: Proton
(08.03.2013 в 13:27)
| | ну кто быстрее тот и в коде :) | |
|
|
|
|
|
|
|
для: Valick
(08.03.2013 в 16:04)
| | Ну вот этот вариант походу и быстрее. | |
|
|
|
|
|
|
|
для: Proton
(06.03.2013 в 20:20)
| | Если проблема только в этом:
>И вот тут начинаются проблемы $address_ranges[$i]['end'] будет присвоен IP недоступного коммутатора, а на самом деле надо присвоить предыдущий IP...
то, что вам мешает сделать:
<?php
$address_ranges[$i]['end'] = long2ip(ip2long($ip_dlink)-1);
|
| |
|
|
|
|
|
|
|
для: Igorek
(08.03.2013 в 09:45)
| | точнее даже:
<?php
$address_ranges[$i]['end'] = long2ip($i-1);
|
| |
|
|
|