The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"inet_ntoa и inet_aton"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(??) on 14-Апр-05, 20:16  (MSK)
В нескольких программах (perl) мне нужно ( напрмер, для скорости сравнения )
испольковать ip аддреса в численном виде.
идею перевода заимствовал из mysql

sub to_num {
my @s = split /\./, $_[0];
my $num = $s[0]*256**3 +  $s[1]*256**2 + $s[2]*256 + $s[3];
return $num;
}

но вот, с обратным переводом - проблемма. Я для него ипользу приведенный ниже алогитм, который, мягко говоря "не оптимальный". Есть-ли более красивый способ?

sub from_num {
my @ipc; # ip in chars
my $curr = $_[0];
push @ipc, int($curr/256**3);
$curr -= $ipc[0]*256**3;
push @ipc, int($curr/256**2);
$curr -= $ipc[1]*256**2;
push @ipc, int($curr/256);
$curr -= $ipc[2]*256;
push @ipc, $curr;
return join('.',@ipc);
}

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "inet_ntoa и inet_aton" 
Сообщение от madskull Искать по авторуВ закладки(ok) on 14-Апр-05, 20:47  (MSK)
Странное решение они используют... может быть, просто для того, чтобы избежать неверного сравнивания адресов вида 1.2.3.4 и 001.002.003.004?
Потому что в perl'e расходы на преобразования будут намного больше, чем сравнение строк.
Если мне склероз не изменяет, в perl'e все хранится в виде строк, так что нет нужды переводить из строки в числа.

Ну, а если уж очень хочется, то может так красивше?
sub from_num {
   my $n = shift;
    return int($n/16777216).".".int($n%16777216/65536).".".
        int($n%65536/256).".".int($n%256)
}

Да, забыл написать, что может еще правильнее будет использовать inet_aton/inet_ntoa
из пакета Socket?

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(??) on 14-Апр-05, 21:50  (MSK)
>Странное решение они используют... может быть, просто для того, чтобы избежать неверного
>сравнивания адресов вида 1.2.3.4 и 001.002.003.004?
>Потому что в perl'e расходы на преобразования будут намного больше, чем сравнение
>строк.
>Если мне склероз не изменяет, в perl'e все хранится в виде строк,
>так что нет нужды переводить из строки в числа.

Быстрее происходит сарвнение больше/меньше, наприер для определения принадлежности ip к диапозону. И, наприпер, в таком виде удобнее хранить в sqlite базе (маньше места, быстрее выборки, если везде - integer).

>Ну, а если уж очень хочется, то может так красивше?
>sub from_num {
>   my $n = shift;
>    return int($n/16777216).".".int($n777216/65536).".".
>        int($ne536/256).".".int($n%6)
>}
Сасибо. Замеров скорости не проводил, но на взгляд это должно работать быстрее.

>Да, забыл написать, что может еще правильнее будет использовать inet_aton/inet_ntoa
>из пакета Socket?
он возвращет "opaque string (if programming in C, struct in_addr)" а, это для мого случая не подходит.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "inet_ntoa и inet_aton" 
Сообщение от ACCA Искать по авторуВ закладки(ok) on 14-Апр-05, 21:23  (MSK)
sub from_num {
  return pack("C4", @_);
}

Только оно (как и твой алгоритм) у тебя не будет работать на другой архитектуре.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(??) on 15-Апр-05, 00:37  (MSK)
>sub from_num {
>  return pack("C4", @_);
>}
на архитекту, отличной от x86? можете объяснить подробнее?


  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "inet_ntoa и inet_aton" 
Сообщение от ACCA Искать по авторуВ закладки(ok) on 19-Апр-05, 08:13  (MSK)
>на архитекту, отличной от x86? можете объяснить подробнее?

Проблема в том, как выглядит число, скажем 256, в двоичном виде.

Его можно записать как 00000001 00000000 (старший байт в младшем адресе), либо как 00000000 00000001 (младший байт в младшем адресе). В архитектуре DEC (и последователях вроде SPARC) первым идёт старший байт (big endian). В архитектуре IBM (и последователях вроде x86) первым идёт младший байт (little endian).

В результате адрес 192.1.2.3 на x86 выглядит как 0x030201C0, а на SPARC как 0xC0010203. inet_ntoa и inet_aton на любой архитектуре преобразуют строку в "правильное сетевое" число (в действительности big endian).

Самодельные функции должны пользоваться системными вызовами htonl и ntohl, чтобы делать так же.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 15-Апр-05, 21:54  (MSK)
>sub from_num {
>  return pack("C4", @_);
>}
>
>Только оно (как и твой алгоритм) у тебя не будет работать на
>другой архитектуре.


ну, у тебя получится строка из 4 байт
а человеку надо число..
так что

perl -e 'printf("result:%X\n",unpack("N",pack("C4",split(/\./,$ARGV[0]))))' 254.128.64.32
result:FE804020

и вполне себе портабельно :)

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "inet_ntoa и inet_aton" 
Сообщение от sashacrane Искать по авторуВ закладки(??) on 19-Апр-05, 03:35  (MSK)
А такой вариант?
Полагаю, что операции с побитовыми сдвигами и AND'ами НАМНОГО быстрее работают.

sub ipToNum(){
    my $sIP = shift;
    my $res;
    $res=($1<<24)+($2<<16)+($3<<8)+$4 if $sIP =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    $res=($1<<24)+($2<<16)+($3<<8) if $sIP =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    $res=($1<<24)+($2<<16) if $sIP =~ m/^(\d{1,3})\.(\d{1,3})$/;
    $res=($1<<24) if $sIP =~ m/^(\d{1,3})$/;
    return $res;
}

sub ipToStr(){
    my $nIP = shift;
    my $res = (($nIP>>24) & 255) .".". (($nIP>>16) & 255) .".". (($nIP>>8) & 255) .".". ($nIP & 255);
    return $res;
}

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(??) on 20-Апр-05, 22:29  (MSK)
Вот результат тестов на скорость:
To numeric
Original: 4.419041
By sashacrane: 8.723555

From  numeric
Original: 6.641646
By madskull: 3.943649
By sashacrane: 3.610706

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "inet_ntoa и inet_aton" 
Сообщение от sashacrane Искать по авторуВ закладки(??) on 21-Апр-05, 05:32  (MSK)
А вот если эти строки убрать будет бустрее, но функция будет работать только для полного IP.
    $res=($1<<24)+($2<<16)+($3<<8) if $sIP =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    $res=($1<<24)+($2<<16) if $sIP =~ m/^(\d{1,3})\.(\d{1,3})$/;
    $res=($1<<24) if $sIP =~ m/^(\d{1,3})$/;
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(??) on 21-Апр-05, 13:02  (MSK)
не сильно лучше стало.
To numeric
Original: 3.930417
By sashacrane: 4.403279

PS кто-нибуть знает имет-ли спысл учитывать накладные расходы на вызов процедуры?

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

11. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 21-Апр-05, 18:52  (MSK)
ip to num на миллион адресов:

вариант rWizard - 7.240
вариант твой - 11.223
вариант мой - 5.556

sub ipToNum(){
    my $sIP = shift;
    return unpack("N",pack("C4",split(/\./,$sIP)));
}

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

12. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 21-Апр-05, 19:16  (MSK)
еще чуть-чуть можно ускорить(4.820), убрав двойные кавычки и не используя локальную переменную:

sub ipToNum(){
     return unpack('N',pack('C4',split(/\./,$_[0])));
}


  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

13. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(ok) on 21-Апр-05, 19:26  (MSK)
проблемма в том, что
# perl -e'print unpack('N',pack('C4',split(/\./,'127.0.0.1')));print"\n"'  
0

или я что-то не понял?
что возвращает твоя процедура?

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

15. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 21-Апр-05, 19:31  (MSK)
>проблемма в том, что
># perl -e'print unpack('N',pack('C4',split(/\./,'127.0.0.1')));print"\n"'
>0
>
>или я что-то не понял?
>что возвращает твоя процедура?


$ perl -e 'print  unpack("N",pack("C4",split(/\./,"127.0.0.1"))) ."\n"'
2130706433

на кавычки посмотри...
ты ж в командной строке делаешь, perl -e ' ... '

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

14. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 21-Апр-05, 19:28  (MSK)
>ip to num на миллион адресов:
>
>вариант rWizard - 7.240
>вариант твой - 11.223
с убранными строками (только для полного ip) вариант sashacrane - 7.203

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

16. "inet_ntoa и inet_aton" 
Сообщение от rWizard emailИскать по авторуВ закладки(ok) on 22-Апр-05, 16:11  (MSK)
в итоге:
To numeric
By rWizard: 4.448895
By qq: 2.827952
By sashacrane: 5.078883

From  numeric
By rWizard: 5.27202
By madskull: 3.300532
By sashacrane: 2.67985

те, самые быстрые
sub ipToNum($){
     return unpack('N',pack('C4',split(/\./,$_[0])));
}

sub ipToStr(){
    my $nIP = shift;
    my $res = (($nIP>>24) & 255) .".". (($nIP>>16) & 255) .".". (($nIP>>8) & 255) .".". ($nIP & 255);
    return $res;
}

Спасибо всем участвавашим.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

17. "inet_ntoa и inet_aton" 
Сообщение от qq Искать по авторуВ закладки(??) on 22-Апр-05, 19:26  (MSK)
>те, самые быстрые
>sub ipToNum($){
>     return unpack('N',pack('C4',split(/\./,$_[0])));
>}
>
>sub ipToStr(){
>    my $nIP = shift;
>    my $res = (($nIP>>24) & 255) .".". (($nIP>>16) & 255) .".". (($nIP>>8) & 255) .".". ($nIP & 255);
>    return $res;
>}
>
>Спасибо всем участвавашим.

ну, самыс быстрым ip_to_num всеже будет использование inet_aton из модуля Socket.

use Socket;
sub ip_to_num {
    return unpack('N',inet_aton($_[0]));
}


однако num_to_ip все же быстрее с использованием сдвигов, как сделал sashacrane - т.к. при использовании inet_ntoa надо сначала число перевести в строку из 4 байт, чтобы inet_ntoa это скушал. Если не делать этот pack - то разница исчезает.

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру