[PHP] IP subnetmask conversie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Ethirty
  • Registratie: September 2007
  • Laatst online: 18:17

Ethirty

Who...me?

Topicstarter
Ik ben wat aan het stoeien met php (heb geen intentie/illusie om een echte programmeur te lijken). Nu probeer ik naar mijn idee iets vrij simpels: namelijk de /xx ip-subnetmask notatie omzetten naar dotted decimal (/23 -> 255.255.254.0). Ik heb daarvoor eerst het volgende bedacht:
PHP:
1
2
3
4
5
6
7
8
9
10
//Change subnetmask from /xx to aaa.bbb.ccc.ddd notation where xx=$a
$tmpbin="";
//make 32-bit binary from $a
for ($i=1; $i<=$a; $i++) {
  $tmpbin .= "1";
}

for ($j=1; $j<=(32-$a); $j++) {
  $tmpbin .= "0";
}

al lezende in het boek kwam ik achter een andere methode, die me simpeler leek, maar waarvan ik niet weet of die ook 'beter' is:
PHP:
1
2
$tmpbin = str_pad("", $a, '1', STR_PAD_LEFT);
$tmpbin = str_pad($tmpbin, 32, '0', STR_PAD_RIGHT);

Nu heb ik een 32 tekens lange string met eentjes en nulletjes, die ik in 4 stukken van 8 bits wil, dus:
PHP:
1
2
3
4
5
6
7
//split 32-bit in 4 decimal segments
$sub1 = bindec(substr($tmpbin, 0, 8));
$sub2 = bindec(substr($tmpbin, 8, 8));
$sub3 = bindec(substr($tmpbin, 16, 8));
$sub4 = bindec(substr($tmpbin, 24, 8));

$tmpstr = "{$sub1}.{$sub2}.{$sub3}.{$sub4}";

Werkt allemaal prima, maar nu vond ik dat laatste niet zo heel mooi, dus ik zit nu te kijken naar een andere manier om die 32 tekens om te zetten.
PHP:
1
2
//split into array, then implode making dotted notation
$tmpstr = implode(".", (str_split($tmpbin, 8)));

Hiermee krijg ik netjes de 1'en en 0'en gescheiden met een . maar ik wil de decimale notatie, dus probeer ik
PHP:
1
$tmpstr = implode(".", bindec((str_split($tmpbin, 8))));
geeft alleen een fout:
Warning: Wrong parameter count for substr() in \includes\functions.php on line 21
Warning: implode() [function.implode]: Bad arguments. in :\includes\functions.php on line 21
Ik wil dit eigenlijk oplossen zonder loop, maar ik kom er niet uit. Zit ik dan toch aan een loop vast om de arraywaardes om te zetten?

#team_UTC+1

An investment in knowledge always pays the best interest - Benjamin Franklin
You can call me McOverloper  Mini '12 i7/16/256  Air '13 i5/8/256  iPad mini 5 64GB  iPhone SE 128GB


Acties:
  • 0 Henk 'm!

  • OnTracK
  • Registratie: Oktober 2002
  • Nu online
Je kunt i.p.v. een simpele loop ook zoiets als array_map gebruiken. Ik weet niet zeker of het volgende werkt, maar probeer eens wat:

PHP:
1
implode('.', array_map('bindec', str_split($tmpbin, 8)));

Not everybody wins, and certainly not everybody wins all the time.
But once you get into your boat, push off and tie into your shoes.
Then you have indeed won far more than those who have never tried.


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Of je gebruikt gewoon long2ip() :z

[ Voor 33% gewijzigd door Voutloos op 21-07-2008 12:41 ]

{signature}


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Voutloos schreef op maandag 21 juli 2008 @ 12:40:
Of je gebruikt gewoon long2ip() :z
Werkt hier niet he? ;)

Zelf zou ik de code wat anders opzetten, zonder al die tussenstappen. Normaal ben ik tegen codeposten, maar ik had het liggen en de opzet verschilt zodanig van wat je al hebt dat je het anders waarschijnlijk toch niet zou namaken als ik het zonder code zou omschrijven.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$output = '';

$num255 = floor($a / 8);
$middlepartbits = $a % 8;


for($i=1; $i<=$num255; $i++) {
    if($output != '') $output .= '.';
    $output .= '255';
}

if($middlepartbits > 0) {
    $tmp = 256;
    $middlepartnum = 0;
    for($i=1; $i<=$middlepartbits; $i++) {
        $tmp = $tmp/2;
        $middlepartnum += $tmp;
    }
    if($output != '') $output .= '.';
    $output .= $middlepartnum;
}

for($i=1; $i<=4-$num255-($middlepartbits>0); $i++) {
    if($output != '') $output .= '.';
    $output .= '0';
}

echo $output

Acties:
  • 0 Henk 'm!

  • Ethirty
  • Registratie: September 2007
  • Laatst online: 18:17

Ethirty

Who...me?

Topicstarter
@GlowMouse, wat bedoel je met tussenstappen, zoveel zijn het er toch niet?
@OnTrack: dat doet precies wat ik wil! Heb het nu teruggebracht naar slechts 2 regels
PHP:
1
2
3
4
5
6
7
8
9
10
function convert_subnet($a) {
//Change subnetmask from /xx to aaa.bbb.ccc.ddd notation where xx=$a
//create 32-bit subnetmask string
$tmpbin = str_pad(str_pad('', $a, '1'), 32, '0');

//split into array, then implode making dotted decimal notation
$tmpstr = implode('.', array_map('bindec', str_split($tmpbin, 8)));

return $tmpstr;
}

Dit kan misschien zelfs nog wel op 1 regel, maar zo blijft het overzichtelijk.

Dank!

#team_UTC+1

An investment in knowledge always pays the best interest - Benjamin Franklin
You can call me McOverloper  Mini '12 i7/16/256  Air '13 i5/8/256  iPad mini 5 64GB  iPhone SE 128GB


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Ethirty schreef op maandag 21 juli 2008 @ 13:04:
@GlowMouse, wat bedoel je met tussenstappen, zoveel zijn het er toch niet?
Ja ik had je post wat te vluchtig gelezen, ik zag je nog met die substr's knoeien. Maar je blijft de tussenstap houden waarin je alles naar binair omzet. En ondanks veelvuldig gebruik van ingebouwde PHP-functies blijft je code daardoor zo'n 30% langzamer dan mijn code. Maar zolang je de functie niet ontzettend vaak per seconde aanroept maakt dat nauwelijks uit, dus ik zou met je tweeregelige functie verderwerken :)

Acties:
  • 0 Henk 'm!

  • Ethirty
  • Registratie: September 2007
  • Laatst online: 18:17

Ethirty

Who...me?

Topicstarter
Als er 30% verschil in zit ga ik eens kijken of ik jouw code kan gaan snappen, want dat doe ik nu nog niet. Niet dat ik de performance nodig heb, wil gewoon weten hoe die van jou werkt. ;)

edit:
Ah - ik snap 'em. Briljant eigenlijk nu ik zie hoe het werkt.

[ Voor 17% gewijzigd door Ethirty op 21-07-2008 13:38 ]

#team_UTC+1

An investment in knowledge always pays the best interest - Benjamin Franklin
You can call me McOverloper  Mini '12 i7/16/256  Air '13 i5/8/256  iPad mini 5 64GB  iPhone SE 128GB


Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Als je van de stringfuncties afstapt en binair rekent wel.
Je zou het dan bijv. zo kunnen doen:
PHP:
1
2
3
4
5
$a = 23;

$ip = 0xffffffff << ( 32 - $a );

$s = long2ip( $ip );

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Icelus schreef op maandag 21 juli 2008 @ 14:03:
[...]
Als je van de stringfuncties afstapt en binair rekent wel.
Je zou het dan bijv. zo kunnen doen:
PHP:
1
2
3
4
5
$a = 23;

$ip = 0xffffffff << ( 32 - $a );

$s = long2ip( $ip );
***, dacht er niet lang genoeg over na. Dit is de mooiste en snelste oplossing van de genoemde 3 :)

Acties:
  • 0 Henk 'm!

  • Ethirty
  • Registratie: September 2007
  • Laatst online: 18:17

Ethirty

Who...me?

Topicstarter
Hoe zit dat dan met de waarschuwing op php.net? Of verdwijnen de meest linker bitjes in een zwart gat?
Don't right shift for more than 32 bits on 32 bits systems. Don't left shift in case it results to number longer than 32 bits.

#team_UTC+1

An investment in knowledge always pays the best interest - Benjamin Franklin
You can call me McOverloper  Mini '12 i7/16/256  Air '13 i5/8/256  iPad mini 5 64GB  iPhone SE 128GB


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Ethirty schreef op maandag 21 juli 2008 @ 14:25:
Hoe zit dat dan met de waarschuwing op php.net? Of verdwijnen de meest linker bitjes in een zwart gat?
[...]
"zwart gat" ja :P Je krijgt gewoon ongewenst gedrag, dit komt door de manier waarop integers zijn opgeslagen. Maar in dit geval is er geen probleem, aangezien je nooit meer dan 32 bits verschuift ;)
Pagina: 1