PERINGATAN : bilangan bulat yang dihasilkan dari jawaban yang diterima akan salah , karena alamat IP berada dalam urutan jaringan (big-endian), sedangkan ints adalah little-endian pada kebanyakan sistem. Jadi, Anda harus membalik byte sebelum mengonversi. Lihat jawaban saya untuk konversi yang benar. Juga, bahkan untuk IPv4, an inttidak dapat menyimpan alamat yang lebih besar dari 127.255.255.255, misalnya alamat broadcast, jadi gunakan a uint.
Saeb Amini
Jawaban:
137
Integer 32-bit unsigned adalah alamat IPv4. Sementara itu, IPAddress.Addressproperti, meski tidak digunakan lagi, adalah Int64 yang mengembalikan nilai 32-bit unsigned dari alamat IPv4 (tangkapannya adalah, dalam urutan byte jaringan, jadi Anda perlu menukarnya).
Misalnya, google.com lokal saya ada di 64.233.187.99. Itu setara dengan:
64*2^24+233*2^16+187*2^8+99=1089059683
Dan memang, http: // 1089059683 / berfungsi seperti yang diharapkan (setidaknya di Windows, diuji dengan IE, Firefox dan Chrome; meskipun tidak berfungsi di iPhone).
Berikut adalah program uji untuk menunjukkan kedua konversi, termasuk pertukaran byte jaringan / host:
using System;
using System.Net;classApp{staticlongToInt(string addr){// careful of sign extension: convert to uint first;// unsigned NetworkToHostOrder ought to be provided.return(long)(uint)IPAddress.NetworkToHostOrder((int)IPAddress.Parse(addr).Address);}staticstringToAddr(long address){returnIPAddress.Parse(address.ToString()).ToString();// This also works:// return new IPAddress((uint) IPAddress.HostToNetworkOrder(// (int) address)).ToString();}staticvoidMain(){Console.WriteLine(ToInt("64.233.187.99"));Console.WriteLine(ToAddr(1089059683));}}
Dikonfirmasi di Opera 11 di Ubuntu Linux 10.04: itu mengubah int kembali ke bentuk wxyz yang sudah dikenal, dan Berfungsi.
Piskvor meninggalkan gedung
6
IPAddress.Address sudah usang sejak .Net 4.0.
Erik Philips
@ErikPhilips Apakah itu penting jika Anda hanya menggunakan IPv4?
Ray
Itu keputusan arsitektur. Ada pro dan kontra, dan komentar bukanlah tempat terbaik untuk membahas masalah khusus itu.
Erik Philips
1
Anda dapat menggunakan BitConverter.ToUInt32 (IPAddress.Parse (value) .GetAddressBytes (). Reverse (). ToArray () untuk memperbaiki IPAddress.Address sudah usang
Mhmd
43
Berikut adalah sepasang metode untuk mengonversi dari IPv4 ke bilangan bulat yang benar dan sebaliknya:
publicstaticuintConvertFromIpAddressToInteger(string ipAddress){var address =IPAddress.Parse(ipAddress);byte[] bytes = address.GetAddressBytes();// flip big-endian(network order) to little-endianif(BitConverter.IsLittleEndian){Array.Reverse(bytes);}returnBitConverter.ToUInt32(bytes,0);}publicstaticstringConvertFromIntegerToIpAddress(uint ipAddress){byte[] bytes =BitConverter.GetBytes(ipAddress);// flip little-endian to big-endian(network order)if(BitConverter.IsLittleEndian){Array.Reverse(bytes);}returnnewIPAddress(bytes).ToString();}
Alamat IP berada dalam urutan jaringan (big-endian), sedangkan ints adalah little-endian pada Windows, jadi untuk mendapatkan nilai yang benar, Anda harus membalikkan byte sebelum mengonversi pada sistem little-endian.
Juga, bahkan untuk IPv4, an inttidak dapat menyimpan alamat yang lebih besar dari 127.255.255.255, misalnya alamat broadcast (255.255.255.255), jadi gunakan a uint.
Ini tampaknya tidak membuat perbedaan pada Windows yang menggunakan .NET - tidak yakin tentang Mono. Lihat dotnetfiddle.net/cBIOj2
Jesse
2
@ Jesse kebetulan tidak membuat perbedaan untuk masukan Anda 1.1.1.1karena array byte-nya adalah palindromik. Coba dengan yang non-palindromik seperti 127.0.0.1atau 192.168.1.1.
Saeb Amini
Saya melihat masalahnya. Nomor berulang seperti 1.1.1.1, 2.2.2.2, 123.123.123.123selalu menghasilkan hasil yang sama. Untuk anak cucu, lihat biola yang diperbarui: dotnetfiddle.net/aR6fhc
Jesse
Ingin mencatat bahwa saya harus menggunakan System.Net.IPAddressagar ini berfungsi. Bekerja dengan baik!
Shrout1
1
@Jesse itu tidak hanya untuk mengulang angka, tapi untuk semua alamat IP palindromic . Begitu pula 2.1.1.2halnya.
Saeb Amini
40
@Barry Kelly dan @Andrew Hare, sebenarnya, menurut saya mengalikan adalah cara paling jelas untuk melakukan ini (semuanya benar).
Alamat IP "diformat" Int32 dapat dilihat sebagai struktur berikut
[StructLayout(LayoutKind.Sequential,Pack=1)]structIPv4Address{publicByte A;publicByte B;publicByte C;publicByte D;}// to actually cast it from or to an int32 I think you // need to reverse the fields due to little endian
Jadi untuk mengubah alamat ip 64.233.187.99 Anda bisa melakukan:
jadi Anda bisa menambahkannya menggunakan + atau Anda bisa binairy atau bersama-sama. Menghasilkan 0x40E9BB63 yaitu 1089059683. (Menurut pendapat saya, mencari di hex jauh lebih mudah untuk melihat byte)
Jadi Anda bisa menulis fungsinya sebagai:
int ipToInt(int first,int second,int third,int fourth){return(first <<24)|(second <<16)|(third <<8)|(fourth);}
Saya percaya bahwa ip dispesifikasikan sedemikian rupa untuk secara khusus memungkinkan perilaku seperti itu ... pergeseran bit jauh lebih efisien pada kebanyakan mikroprosesor daripada muls dan add.
Ape-inago
1
@ Perkalian kera-inago dengan kekuatan konstan dua biasanya dioptimalkan ke dalam pergeseran bit, fwiw.
Barry Kelly
Alih-alih menggeser bit, Anda dapat menggunakan LayoutKind.Explicitdan FieldOffsetmembalik urutan penyimpanan byte. Tentu saja, itu hanya berfungsi untuk arsitektur little endian. Contoh di github .
RubberDuck
2
Harus menunjukkan yang intditandatangani sehingga jika Anda menggeser 192 dengan 24 bit Anda akan mendapatkan bilangan bulat negatif sehingga kode ini rusak untuk oktet tinggi yang memiliki bit tinggi di tempat pertama.
Reverse()pengembalian tidak berlaku, jadi Anda tidak dapat memanggilnya ToArray()(untuk pembaca mendatang). Sebagai gantinya, tetapkan nilai ke byte yang dibalik, lalu Anda dapat memanggil ToArray ().
Erik Philips
1
Reverse () adalah metode ekstensi IEnumerable. Kode di atas sangat oke.
Semut
3
Metode ini menghasilkan angka negatif untuk IP tertentu (misalnya 140.117.0.0)
lightxx
7
Karena tidak ada yang memposting kode yang menggunakan BitConverterdan benar-benar memeriksa endianness, ini dia:
byte[] ip = address.Split('.').Select(s =>Byte.Parse(s)).ToArray();if(BitConverter.IsLittleEndian){Array.Reverse(ip);}int num =BitConverter.ToInt32(ip,0);
dan kembali:
byte[] ip =BitConverter.GetBytes(num);if(BitConverter.IsLittleEndian){Array.Reverse(ip);}string address =String.Join(".", ip.Select(n => n.ToString()));
Anda perlu menggunakan uint, tetapi ini adalah jawaban yang paling benar di sini.
RubberDuck
1
@RubberDuck: Anda hanya perlu menggunakan uintjika Anda ingin 32 bit data sebagai nomor tak bertanda tangan, dan intmampu menyimpan informasi yang sama. Jika Anda ingin menyimpannya dalam database dan intlebih cocok, Anda membutuhkannya bigintagar dapat menyimpannya dalam bentuk unsigned.
Guffa
1
Uint adalah representasi IMO yang lebih baik. Int yang ditandatangani membutuhkan sedikit untuk tanda, jadi Anda kehilangan alamat di bagian paling atas rentang. Ya, ini dapat menyimpan data yang sama, tetapi akan dikeluarkan sebagai angka negatif, yang bukan merupakan IP yang valid jika Anda mengetiknya di bilah alamat.
RubberDuck
@RubberDuck: Dalam bentuk dan uintAnda juga tidak dapat mengetikkannya di bilah alamat, Anda harus mengonversinya terlebih dahulu ke dalam bentuk teks untuk melakukannya. Hanya karena menggunakan bentuk paling sederhana untuk mengubah sebuah intteks tidak menghasilkan alamat IP yang berfungsi bukanlah argumen yang baik untuk tidak menggunakannya.
Guffa
@RubberDuck: Itu bukan an uint, itu representasi teks dari sebuah uint.
Guffa
7
Saya mengalami beberapa masalah dengan solusi yang dijelaskan, saat menghadapi Alamat IP dengan nilai yang sangat besar. Hasilnya adalah, bahwa thingy byte [0] * 16777216 akan meluap dan menjadi nilai int negatif. apa yang memperbaikinya untuk saya, adalah operasi pengecoran tipe sederhana.
bisakah Anda menjelaskan lebih lanjut tentang ini?
Developerium
3
Pertanyaan saya ditutup, saya tidak tahu mengapa. Jawaban yang diterima di sini tidak sama dengan yang saya butuhkan.
Ini memberi saya nilai integer yang benar untuk sebuah IP ..
publicdoubleIPAddressToNumber(stringIPaddress){int i;string[] arrDec;double num =0;if(IPaddress==""){return0;}else{
arrDec =IPaddress.Split('.');for(i = arrDec.Length-1; i >=0; i = i -1){
num +=((int.Parse(arrDec[i])%256)*Math.Pow(256,(3- i )));}return num;}}
Selama Anda dapat melakukan konversi dengan kedua cara tersebut, saya tidak mengerti mengapa nomor keluaran harus benar asalkan konsisten.
GateKiller
Tergantung pada apa Anda ingin menggunakan nomor tersebut. Anda tidak dapat menggunakan konversi lain untuk melakukan kueri> = dan <= untuk menemukan IP ..
Coolcoder
2
Dengan UInt32 dalam format little-endian yang tepat, berikut dua fungsi konversi sederhana:
Mengumpulkan beberapa jawaban di atas menjadi metode ekstensi yang menangani Ketahanan mesin dan menangani alamat IPv4 yang dipetakan ke IPv6.
publicstaticclassIPAddressExtensions{/// <summary>/// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer./// </summary>/// <param name="address">The address to conver</param>/// <returns>An unsigned integer that represents an IPv4 address.</returns>publicstaticuintToUint(thisIPAddress address){if(address.AddressFamily==AddressFamily.InterNetwork|| address.IsIPv4MappedToIPv6){var bytes = address.GetAddressBytes();if(BitConverter.IsLittleEndian)Array.Reverse(bytes);returnBitConverter.ToUInt32(bytes,0);}thrownewArgumentOutOfRangeException("address","Address must be IPv4 or IPv4 mapped to IPv6");}}
Tes unit:
[TestClass]publicclassIPAddressExtensionsTests{[TestMethod]publicvoidSimpleIp1(){var ip =IPAddress.Parse("0.0.0.15");uint expected =GetExpected(0,0,0,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIp2(){var ip =IPAddress.Parse("0.0.1.15");uint expected =GetExpected(0,0,1,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIpSix1(){var ip =IPAddress.Parse("0.0.0.15").MapToIPv6();uint expected =GetExpected(0,0,0,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIpSix2(){var ip =IPAddress.Parse("0.0.1.15").MapToIPv6();uint expected =GetExpected(0,0,1,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidHighBits(){var ip =IPAddress.Parse("200.12.1.15").MapToIPv6();uint expected =GetExpected(200,12,1,15);Assert.AreEqual(expected, ip.ToUint());}uintGetExpected(uint a,uint b,uint c,uint d){return(a *256u*256u*256u)+(b *256u*256u)+(c *256u)+(d);}}
Saya pikir akan lebih jelas jika Anda menggunakan shift daripada Math.Pow.
Mehrdad Afshari
Ini akan memunculkan pengecualian overflow jika yang pertama adalah> 127. Jawaban Davy Landman adalah cara terbaik untuk melakukan ini.
mhenry1384
int32 ditandatangani sehingga akan mengembalikan nilai negatif> 127 untuk oktet pertama
Mateusz
1
publicboolTryParseIPv4Address(stringvalue,outuint result){IPAddress ipAddress;if(!IPAddress.TryParse(value,out ipAddress)||(ipAddress.AddressFamily!=System.Net.Sockets.AddressFamily.InterNetwork)){
result =0;returnfalse;}
result =BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(),0);returntrue;}
Contoh di atas akan menjadi cara saya pergi .. Satu-satunya hal yang mungkin harus Anda lakukan adalah mengubah ke UInt32 untuk tujuan tampilan, atau tujuan string termasuk menggunakannya sebagai alamat panjang dalam bentuk string.
Yang diperlukan saat menggunakan fungsi IPAddress.Parse (String). Mendesah.
inilah solusi yang saya kerjakan hari ini (seharusnya sudah googling dulu!):
privatestaticstringIpToDecimal2(string ipAddress){// need a shift counterint shift =3;// loop through the octets and compute the decimal versionvar octets = ipAddress.Split('.').Select(p =>long.Parse(p));return octets.Aggregate(0L,(total, octet)=>(total +(octet <<(shift--*8)))).ToString();}
Saya menggunakan LINQ, lambda dan beberapa ekstensi pada generik, jadi meskipun menghasilkan hasil yang sama, ia menggunakan beberapa fitur bahasa baru dan Anda dapat melakukannya dalam tiga baris kode.
Saya punya penjelasan di blog saya jika Anda tertarik.
@Davy Ladman solusi Anda dengan shift sudah benar tetapi hanya untuk ip yang dimulai dengan angka kurang atau sama dengan 99, sebenarnya oktek pertama harus dibuang sampai panjang.
Pokoknya mengkonversi kembali dengan tipe lama cukup sulit karena simpan 64 bit (bukan 32 untuk Ip) dan isi 4 byte dengan nol
metode GetAddressBytes dapat mengembalikan byte dalam urutan terbalik, tergantung apakah mesin tersebut endian atau endian-ness sehingga pernyataan yang benar mungkin untuk beberapa mesin: long m_Address = (address [0] << 24 | address [1] << 16 | alamat [2] << 8 | alamat [3]) & 0x0FFFFFFFF
MiguelSlv
0
Saya perhatikan bahwa System.Net.IPAddress memiliki properti Alamat (System.Int64) dan konstruktor, yang juga menerima tipe data Int64. Jadi Anda dapat menggunakan ini untuk mengonversi alamat IP ke / dari format numerik (meskipun bukan Int32, tetapi Int64).
int
s adalah little-endian pada kebanyakan sistem. Jadi, Anda harus membalik byte sebelum mengonversi. Lihat jawaban saya untuk konversi yang benar. Juga, bahkan untuk IPv4, anint
tidak dapat menyimpan alamat yang lebih besar dari127.255.255.255
, misalnya alamat broadcast, jadi gunakan auint
.Jawaban:
Integer 32-bit unsigned adalah alamat IPv4. Sementara itu,
IPAddress.Address
properti, meski tidak digunakan lagi, adalah Int64 yang mengembalikan nilai 32-bit unsigned dari alamat IPv4 (tangkapannya adalah, dalam urutan byte jaringan, jadi Anda perlu menukarnya).Misalnya, google.com lokal saya ada di
64.233.187.99
. Itu setara dengan:Dan memang, http: // 1089059683 / berfungsi seperti yang diharapkan (setidaknya di Windows, diuji dengan IE, Firefox dan Chrome; meskipun tidak berfungsi di iPhone).
Berikut adalah program uji untuk menunjukkan kedua konversi, termasuk pertukaran byte jaringan / host:
sumber
Berikut adalah sepasang metode untuk mengonversi dari IPv4 ke bilangan bulat yang benar dan sebaliknya:
Contoh
Penjelasan
Alamat IP berada dalam urutan jaringan (big-endian), sedangkan
int
s adalah little-endian pada Windows, jadi untuk mendapatkan nilai yang benar, Anda harus membalikkan byte sebelum mengonversi pada sistem little-endian.Juga, bahkan untuk
IPv4
, anint
tidak dapat menyimpan alamat yang lebih besar dari127.255.255.255
, misalnya alamat broadcast(255.255.255.255)
, jadi gunakan auint
.sumber
1.1.1.1
karena array byte-nya adalah palindromik. Coba dengan yang non-palindromik seperti127.0.0.1
atau192.168.1.1
.1.1.1.1
,2.2.2.2
,123.123.123.123
selalu menghasilkan hasil yang sama. Untuk anak cucu, lihat biola yang diperbarui: dotnetfiddle.net/aR6fhcSystem.Net.IPAddress
agar ini berfungsi. Bekerja dengan baik!2.1.1.2
halnya.@Barry Kelly dan @Andrew Hare, sebenarnya, menurut saya mengalikan adalah cara paling jelas untuk melakukan ini (semuanya benar).
Alamat IP "diformat" Int32 dapat dilihat sebagai struktur berikut
Jadi untuk mengubah alamat ip 64.233.187.99 Anda bisa melakukan:
jadi Anda bisa menambahkannya menggunakan + atau Anda bisa binairy atau bersama-sama. Menghasilkan 0x40E9BB63 yaitu 1089059683. (Menurut pendapat saya, mencari di hex jauh lebih mudah untuk melihat byte)
Jadi Anda bisa menulis fungsinya sebagai:
sumber
LayoutKind.Explicit
danFieldOffset
membalik urutan penyimpanan byte. Tentu saja, itu hanya berfungsi untuk arsitektur little endian. Contoh di github .int
ditandatangani sehingga jika Anda menggeser 192 dengan 24 bit Anda akan mendapatkan bilangan bulat negatif sehingga kode ini rusak untuk oktet tinggi yang memiliki bit tinggi di tempat pertama.Coba yang ini:
sumber
Reverse()
pengembalian tidak berlaku, jadi Anda tidak dapat memanggilnyaToArray()
(untuk pembaca mendatang). Sebagai gantinya, tetapkan nilai ke byte yang dibalik, lalu Anda dapat memanggil ToArray ().IEnumerable
. Kode di atas sangat oke.Karena tidak ada yang memposting kode yang menggunakan
BitConverter
dan benar-benar memeriksa endianness, ini dia:dan kembali:
sumber
uint
jika Anda ingin 32 bit data sebagai nomor tak bertanda tangan, danint
mampu menyimpan informasi yang sama. Jika Anda ingin menyimpannya dalam database danint
lebih cocok, Anda membutuhkannyabigint
agar dapat menyimpannya dalam bentuk unsigned.uint
Anda juga tidak dapat mengetikkannya di bilah alamat, Anda harus mengonversinya terlebih dahulu ke dalam bentuk teks untuk melakukannya. Hanya karena menggunakan bentuk paling sederhana untuk mengubah sebuahint
teks tidak menghasilkan alamat IP yang berfungsi bukanlah argumen yang baik untuk tidak menggunakannya.uint
, itu representasi teks dari sebuahuint
.Saya mengalami beberapa masalah dengan solusi yang dijelaskan, saat menghadapi Alamat IP dengan nilai yang sangat besar. Hasilnya adalah, bahwa thingy byte [0] * 16777216 akan meluap dan menjadi nilai int negatif. apa yang memperbaikinya untuk saya, adalah operasi pengecoran tipe sederhana.
sumber
Kebalikan dari fungsi Davy Landman
sumber
Pertanyaan saya ditutup, saya tidak tahu mengapa. Jawaban yang diterima di sini tidak sama dengan yang saya butuhkan.
Ini memberi saya nilai integer yang benar untuk sebuah IP ..
sumber
Dengan UInt32 dalam format little-endian yang tepat, berikut dua fungsi konversi sederhana:
sumber
Mengumpulkan beberapa jawaban di atas menjadi metode ekstensi yang menangani Ketahanan mesin dan menangani alamat IPv4 yang dipetakan ke IPv6.
Tes unit:
sumber
Jika Anda tertarik dengan fungsinya, bukan hanya jawabannya di sini adalah cara melakukannya:
dengan
first
melaluifourth
menjadi segmen dari alamat IPv4.sumber
sumber
Contoh di atas akan menjadi cara saya pergi .. Satu-satunya hal yang mungkin harus Anda lakukan adalah mengubah ke UInt32 untuk tujuan tampilan, atau tujuan string termasuk menggunakannya sebagai alamat panjang dalam bentuk string.
Yang diperlukan saat menggunakan fungsi IPAddress.Parse (String). Mendesah.
sumber
inilah solusi yang saya kerjakan hari ini (seharusnya sudah googling dulu!):
Saya menggunakan LINQ, lambda dan beberapa ekstensi pada generik, jadi meskipun menghasilkan hasil yang sama, ia menggunakan beberapa fitur bahasa baru dan Anda dapat melakukannya dalam tiga baris kode.
Saya punya penjelasan di blog saya jika Anda tertarik.
tepuk tangan, -jc
sumber
Saya pikir ini salah: "65536" ==> 0.0.255.255 "Seharusnya:" 65535 "==> 0.0.255.255" atau "65536" ==> 0.1.0.0 "
sumber
@Davy Ladman solusi Anda dengan shift sudah benar tetapi hanya untuk ip yang dimulai dengan angka kurang atau sama dengan 99, sebenarnya oktek pertama harus dibuang sampai panjang.
Pokoknya mengkonversi kembali dengan tipe lama cukup sulit karena simpan 64 bit (bukan 32 untuk Ip) dan isi 4 byte dengan nol
Nikmati!
Massimo
sumber
Dengan asumsi Anda memiliki Alamat IP dalam format string (mis. 254.254.254.254)
sumber
Keluaran: 10101005056
sumber
sumber
Saya perhatikan bahwa System.Net.IPAddress memiliki properti Alamat (System.Int64) dan konstruktor, yang juga menerima tipe data Int64. Jadi Anda dapat menggunakan ini untuk mengonversi alamat IP ke / dari format numerik (meskipun bukan Int32, tetapi Int64).
sumber
Lihatlah beberapa contoh parsing gila di .Net's IPAddress.Parse: ( MSDN )
"65536" ==> 0.0.255.255
"20.2" ==> 20.0.0.2
"20.65535" ==> 20.0.255.255
"128.1.2" ==> 128.1.0.2
sumber