답변:
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)이고 int
s는 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()));
uint
32 비트 데이터를 부호없는 숫자로 원하는 경우 에만를 사용하면 됩니다 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
.