답변:
32 비트 부호없는 정수 는 IPv4 주소입니다. 한편,IPAddress.Address 속성은 더 이상 사용되지 않지만 IPv4 주소의 서명되지 않은 32 비트 값을 반환하는 Int64입니다 (캐치는 네트워크 바이트 순서이므로 교체해야 함).
예를 들어 내 로컬 google.com은에 64.233.187.99있습니다. 이는 다음과 동일합니다.
64*2^24 + 233*2^16 + 187*2^8 + 99
= 1089059683
그리고 실제로 http : // 1089059683 / 은 예상대로 작동합니다 (적어도 Windows에서는 IE, Firefox 및 Chrome에서 테스트되었지만 iPhone에서는 작동하지 않음).
다음은 네트워크 / 호스트 바이트 스와핑을 포함하여 두 변환을 모두 보여주는 테스트 프로그램입니다.
using System;
using System.Net;
class App
{
static long ToInt(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);
}
static string ToAddr(long address)
{
return IPAddress.Parse(address.ToString()).ToString();
// This also works:
// return new IPAddress((uint) IPAddress.HostToNetworkOrder(
// (int) address)).ToString();
}
static void Main()
{
Console.WriteLine(ToInt("64.233.187.99"));
Console.WriteLine(ToAddr(1089059683));
}
}
다음은 IPv4에서 올바른 정수 로 변환하는 방법입니다 .
public static uint ConvertFromIpAddressToInteger(string ipAddress)
{
var address = IPAddress.Parse(ipAddress);
byte[] bytes = address.GetAddressBytes();
// flip big-endian(network order) to little-endian
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return BitConverter.ToUInt32(bytes, 0);
}
public static string ConvertFromIntegerToIpAddress(uint ipAddress)
{
byte[] bytes = BitConverter.GetBytes(ipAddress);
// flip little-endian to big-endian(network order)
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return new IPAddress(bytes).ToString();
}
예
ConvertFromIpAddressToInteger("255.255.255.254"); // 4294967294
ConvertFromIntegerToIpAddress(4294967294); // 255.255.255.254
설명
IP 주소는 네트워크 순서 (big-endian)이고 ints는 Windows에서 little-endian이므로 올바른 값을 얻으려면 little-endian 시스템에서 변환하기 전에 바이트를 반대로해야합니다.
또한 IPv4 이, int보다 큰 주소를 물을 수 없습니다 127.255.255.255브로드 캐스트 주소, 예를 (255.255.255.255), 그래서를 사용합니다 uint.
1.1.1.1는 바이트 배열이 회문이기 때문에 입력에 차이를 만들지 않습니다 . 비 회문 같은 사람과 시도 127.0.0.1나 192.168.1.1.
1.1.1.1, 와 같이 반복되는 숫자 2.2.2.2는 123.123.123.123항상 동일한 결과를 생성합니다. 후손에 대해서는 업데이트 된 바이올린을 참조하십시오. dotnetfiddle.net/aR6fhc
System.Net.IPAddress이 작업 을 수행 하기 위해 사용해야 했습니다. 잘 작동합니다!
2.1.1.2동일합니다.
@Barry Kelly와 @Andrew Hare는 사실 곱셈이이 작업을 수행하는 가장 명확한 방법이라고 생각하지 않습니다 (정말 정확합니다).
Int32 "형식화 된"IP 주소는 다음 구조로 볼 수 있습니다.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IPv4Address
{
public Byte A;
public Byte B;
public Byte C;
public Byte D;
}
// to actually cast it from or to an int32 I think you
// need to reverse the fields due to little endian
따라서 IP 주소 64.233.187.99를 변환하려면 다음을 수행하십시오.
(64 = 0x40) << 24 == 0x40000000
(233 = 0xE9) << 16 == 0x00E90000
(187 = 0xBB) << 8 == 0x0000BB00
(99 = 0x63) == 0x00000063
---------- =|
0x40E9BB63
그래서 당신은 +를 사용하여 그것들을 더할 수 있습니다. 결과는 1089059683 인 0x40E9BB63입니다. (내 의견으로는 16 진수로 보면 바이트를 보는 것이 훨씬 쉽습니다)
따라서 함수를 다음과 같이 작성할 수 있습니다.
int ipToInt(int first, int second,
int third, int fourth)
{
return (first << 24) | (second << 16) | (third << 8) | (fourth);
}
LayoutKind.Explicit와 FieldOffset바이트가 저장되는 순서를 반대로. 물론 이는 리틀 엔디안 아키텍처에서만 작동합니다. github의 예 .
int이 코드는 높은 옥텟은 처음에 높은 비트있는을 위해 고장 있도록 음의 정수를 얻을 것이다 (192) (24)에 의해 비트를 이동하면 너무 서명됩니다.
이것을 시도하십시오 :
private int IpToInt32(string ipAddress)
{
return BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(), 0);
}
private string Int32ToIp(int ipAddress)
{
return new IPAddress(BitConverter.GetBytes(ipAddress).Reverse().ToArray()).ToString();
}
Reverse()void를 반환하므로 ToArray()(향후 독자를 위해) 호출 할 수 없습니다 . 대신 반전 된 바이트에 값을 할당 한 다음 ToArray ()를 호출 할 수 있습니다.
IEnumerable. 위의 코드는 완벽하게 괜찮습니다.
BitConverter엔디안 을 사용 하고 실제로 확인 하는 코드를 게시 한 사람이 아무도 없으므로 다음 과 같습니다.
byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray();
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
int num = BitConverter.ToInt32(ip, 0);
그리고 뒤로 :
byte[] ip = BitConverter.GetBytes(num);
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
string address = String.Join(".", ip.Select(n => n.ToString()));
uint32 비트 데이터를 부호없는 숫자로 원하는 경우 에만를 사용하면 됩니다 int.는 동일한 정보를 보유 할 수 있습니다. 데이터베이스에 저장하려는 경우 int더 적합 bigint하며 서명되지 않은 형식으로 저장할 수 있어야합니다.
uint주소 표시 줄에 입력 할 수없는 형식의 경우 먼저 텍스트 형식으로 변환해야합니다. int를 텍스트로 변환하는 가장 간단한 형식을 사용하는 것이 작동하는 IP 주소를 생성하지 않기 때문에 사용 하지 않는 것에 대한 좋은 주장이 아닙니다.
uint의 텍스트 표현이다 그, uint.
매우 큰 값을 가진 IP 주소에 직면했을 때 설명 된 솔루션에서 몇 가지 문제가 발생했습니다. 그 결과 byte [0] * 16777216이 오버플로되어 음의 int 값이됩니다. 나를 위해 그것을 고친 것은 간단한 유형의 주조 작업입니다.
public static long ConvertIPToLong(string ipAddress)
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(ipAddress, out ip))
{
byte[] bytes = ip.GetAddressBytes();
return
16777216L * bytes[0] +
65536 * bytes[1] +
256 * bytes[2] +
bytes[3]
;
}
else
return 0;
}
Davy Landman의 기능의 반대
string IntToIp(int d)
{
int v1 = d & 0xff;
int v2 = (d >> 8) & 0xff;
int v3 = (d >> 16) & 0xff;
int v4 = (d >> 24);
return v4 + "." + v3 + "." + v2 + "." + v1;
}
내 질문이 종료되었습니다. 이유를 모르겠습니다. 여기서 받아 들여지는 대답은 내가 필요한 것과 동일하지 않습니다.
이것은 나에게 IP에 대한 올바른 정수 값을 제공합니다 ..
public double IPAddressToNumber(string IPaddress)
{
int i;
string [] arrDec;
double num = 0;
if (IPaddress == "")
{
return 0;
}
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;
}
}
적절한 리틀 엔디안 형식의 UInt32를 사용하면 다음과 같은 두 가지 간단한 변환 함수가 있습니다.
public uint GetIpAsUInt32(string ipString)
{
IPAddress address = IPAddress.Parse(ipString);
byte[] ipBytes = address.GetAddressBytes();
Array.Reverse(ipBytes);
return BitConverter.ToUInt32(ipBytes, 0);
}
public string GetIpAsString(uint ipVal)
{
byte[] ipBytes = BitConverter.GetBytes(ipVal);
Array.Reverse(ipBytes);
return new IPAddress(ipBytes).ToString();
}
위의 몇 가지 답변을 머신의 Endianness를 처리하고 IPv6에 매핑 된 IPv4 주소를 처리하는 확장 방법으로 조합했습니다.
public static class IPAddressExtensions
{
/// <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>
public static uint ToUint(this IPAddress address)
{
if (address.AddressFamily == AddressFamily.InterNetwork || address.IsIPv4MappedToIPv6)
{
var bytes = address.GetAddressBytes();
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
throw new ArgumentOutOfRangeException("address", "Address must be IPv4 or IPv4 mapped to IPv6");
}
}
단위 테스트 :
[TestClass]
public class IPAddressExtensionsTests
{
[TestMethod]
public void SimpleIp1()
{
var ip = IPAddress.Parse("0.0.0.15");
uint expected = GetExpected(0, 0, 0, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIp2()
{
var ip = IPAddress.Parse("0.0.1.15");
uint expected = GetExpected(0, 0, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIpSix1()
{
var ip = IPAddress.Parse("0.0.0.15").MapToIPv6();
uint expected = GetExpected(0, 0, 0, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIpSix2()
{
var ip = IPAddress.Parse("0.0.1.15").MapToIPv6();
uint expected = GetExpected(0, 0, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void HighBits()
{
var ip = IPAddress.Parse("200.12.1.15").MapToIPv6();
uint expected = GetExpected(200, 12, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
uint GetExpected(uint a, uint b, uint c, uint d)
{
return
(a * 256u * 256u * 256u) +
(b * 256u * 256u) +
(c * 256u) +
(d);
}
}
기능에 관심이 있다면 여기에 대한 대답은 어떻게 수행되는지입니다.
int ipToInt(int first, int second,
int third, int fourth)
{
return Convert.ToInt32((first * Math.Pow(256, 3))
+ (second * Math.Pow(256, 2)) + (third * 256) + fourth);
}
IPv4 주소의 세그먼트 를 first통해 fourth.
public bool TryParseIPv4Address(string value, out uint result)
{
IPAddress ipAddress;
if (!IPAddress.TryParse(value, out ipAddress) ||
(ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork))
{
result = 0;
return false;
}
result = BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(), 0);
return true;
}
public static Int32 getLongIPAddress(string ipAddress)
{
return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0));
}
위의 예는 내가가는 길이다 .. 당신이 할 수있는 유일한 것은 디스플레이 목적으로 UInt32로 변환하는 것 뿐이다. 또는 문자열 형식의 긴 주소로 사용하는 것을 포함하여 문자열 목적으로 변환하는 것이다.
IPAddress.Parse (String) 함수를 사용할 때 필요한 것입니다. 한숨.
오늘 제가 해결 한 해결책은 다음과 같습니다 (먼저 봤어야했습니다!).
private static string IpToDecimal2(string ipAddress)
{
// need a shift counter
int shift = 3;
// loop through the octets and compute the decimal version
var octets = ipAddress.Split('.').Select(p => long.Parse(p));
return octets.Aggregate(0L, (total, octet) => (total + (octet << (shift-- * 8)))).ToString();
}
LINQ, lambda 및 일부 확장을 제네릭에 사용하고 있으므로 동일한 결과를 생성하는 동안 새로운 언어 기능 중 일부를 사용하며 세 줄의 코드로 수행 할 수 있습니다.
관심이 있다면 내 블로그에 설명이 있습니다.
건배, -jc
잘못된 것 같습니다. "65536"==> 0.0.255.255 "다음과 같이해야합니다."65535 "==> 0.0.255.255"또는 "65536"==> 0.1.0.0 "
@Davy Ladman 시프트를 사용하는 솔루션은 corrent이지만 99보다 작거나 같은 숫자로 시작하는 ip에 대해서만 사실 첫 번째 옥 텍트는 long으로 캐스팅되어야합니다.
어쨌든 long 유형으로 다시 변환하는 것은 64 비트 (IP의 경우 32가 아님)를 저장하고 4 바이트를 0으로 채우기 때문에 매우 어렵습니다.
static uint ToInt(string addr)
{
return BitConverter.ToUInt32(IPAddress.Parse(addr).GetAddressBytes(), 0);
}
static string ToAddr(uint address)
{
return new IPAddress(address).ToString();
}
즐겨!
마시모
var address = IPAddress.Parse("10.0.11.174").GetAddressBytes();
long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF);
int됩니다. 따라서 변환하기 전에 바이트를 반대로해야합니다. 올바른 변환에 대해서는 내 대답 을 참조하십시오 . 또한,도 IPv4를 들어,이int보다 큰 주소를 물을 수 없습니다127.255.255.255, 예를 들어, 브로드 캐스트 주소를, 그래서를 사용합니다uint.