표준 IPv4 주소를 정수로 변환하는 함수를 찾고 있습니다. 반대로 수행 할 기능에 사용할 수있는 보너스 포인트.
솔루션은 C #이어야합니다.
답변
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
.
답변
@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);
}
답변
이것을 시도하십시오 :
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();
}
답변
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()));
답변
매우 큰 값을 가진 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;
}