[C#] 로컬 IP 주소 얻기

인터넷에는 IP 주소를 얻는 방법을 보여주는 여러 곳이 있습니다. 그리고 많은 사람들이이 예제처럼 보입니다 :

String strHostName = string.Empty;
// Getting Ip address of local machine...
// First get the host name of local machine.
strHostName = Dns.GetHostName();
Console.WriteLine("Local Machine's Host Name: " + strHostName);
// Then using host name, get the IP address list..
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEntry.AddressList;

for (int i = 0; i < addr.Length; i++)
{
    Console.WriteLine("IP Address {0}: {1} ", i, addr[i].ToString());
}
Console.ReadLine();

이 예에서는 여러 개의 IP 주소를 얻지 만 라우터가 프로그램을 실행하는 컴퓨터에 할당하는 IP 주소를 얻는 데 관심이 있습니다. 예.

네트워크에 연결되어 있지 않고 라우터가없는 모뎀을 통해 인터넷에 직접 연결되어 있으면 오류가 발생합니다. 컴퓨터가 C #으로 네트워크에 연결되어 있고 LAN IP 주소를 가져 오는지 어떻게 알 수 있습니까?



답변

로컬 IP 주소를 얻으려면 :

public static string GetLocalIPAddress()
{
    var host = Dns.GetHostEntry(Dns.GetHostName());
    foreach (var ip in host.AddressList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork)
        {
            return ip.ToString();
        }
    }
    throw new Exception("No network adapters with an IPv4 address in the system!");
}

연결되어 있는지 확인하려면 :

System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();


답변

로컬 컴퓨터에서 사용 가능한 다중 IP 주소가있을 때 더 정확한 방법이 있습니다. ConnectUDP 소켓에서 로컬 엔드 포인트를 읽습니다.

string localIP;
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
    socket.Connect("8.8.8.8", 65530);
    IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
    localIP = endPoint.Address.ToString();
}

ConnectUDP 소켓의 경우 다음과 같은 효과가 있습니다. Send/ 의 대상을 설정하고 Recv다른 주소에서 모든 패킷을 버리고 사용하는 소켓을 “연결된”상태로 전송하고 해당 필드를 설정합니다. 여기에는 시스템의 라우팅 테이블에 따라 대상에 대한 경로가 있는지 확인하고 이에 따라 로컬 엔드 포인트를 설정하는 것이 포함됩니다. 마지막 부분은 공식적으로 문서화되지 않은 것으로 보이지만 버전과 배포판에서 Windows 와 Linux 모두에서 안정적으로 작동하는 Berkeley 소켓 API (UDP “연결된”상태의 부작용) 의 핵심적인 특성처럼 보입니다 .

따라서이 방법은 지정된 원격 호스트에 연결하는 데 사용되는 로컬 주소를 제공합니다. 실제 연결이 설정되지 않았으므로 지정된 원격 IP에 도달 할 수 없습니다.


답변

Linq (예 : .Net 3.0+)를 활용하기 위해 Mrcheif의 코드를 리팩토링했습니다. .

private IPAddress LocalIPAddress()
{
    if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
    {
        return null;
    }

    IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());

    return host
        .AddressList
        .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
}

🙂


답변

나는 이것이 죽은 말을 걷어차는 것을 알고 있지만 어쩌면 이것은 누군가를 도울 수 있습니다. 로컬 IP 주소를 찾는 방법을 찾기 위해 모든 곳을 살펴 봤지만 어디에서나 사용한다고 말합니다.

Dns.GetHostEntry(Dns.GetHostName());

컴퓨터에 할당 된 모든 주소 만 가져 오기 때문에이 점이 마음에 들지 않습니다. 여러 네트워크 인터페이스가있는 경우 (대부분의 모든 컴퓨터에서 현재 수행하는 작업) 어떤 주소가 어떤 네트워크 인터페이스와 연결되는지 알 수 없습니다. 많은 연구를 한 후 NetworkInterface 클래스를 사용하고 정보를 빼내는 함수를 만들었습니다. 이런 식으로 인터페이스의 유형 (이더넷, 무선, 루프백, 터널 등), 활성 여부에 관계없이 훨씬 더 많은 것을 알 수 있습니다.

public string GetLocalIPv4(NetworkInterfaceType _type)
{
    string output = "";
    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
        {
            foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                {
                    output = ip.Address.ToString();
                }
            }
        }
    }
    return output;
}

이더넷 네트워크 인터페이스 호출의 IPv4 주소를 가져 오려면 다음을 수행하십시오.

GetLocalIPv4(NetworkInterfaceType.Ethernet);

또는 무선 인터페이스 :

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

무선 인터페이스의 IPv4 주소를 가져 오려고하지만 컴퓨터에 무선 카드가 설치되어 있지 않으면 빈 문자열 만 반환합니다. 이더넷 인터페이스도 마찬가지입니다.

이것이 누군가를 돕기를 바랍니다! 🙂

편집하다:

이 함수는 IP 주소를 사용하는 것보다 훨씬 더 나은 방법으로 IP 주소를 추출하는 경우에도 @NasBanov 덕분 Dns.GetHostEntry(Dns.GetHostName())에 단일 인터페이스에서 동일한 유형의 여러 인터페이스 또는 여러 IP 주소를 지원하는 데별로 좋지 않습니다. . 여러 주소가 할당 된 경우 단일 IP 주소 만 반환합니다. 할당 된 주소를 모두 반환하려면 원래 함수를 조작하여 단일 문자열 대신 항상 배열을 반환하면됩니다. 예를 들면 다음과 같습니다.

public static string[] GetAllLocalIPv4(NetworkInterfaceType _type)
{
    List<string> ipAddrList = new List<string>();
    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
        {
            foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                {
                    ipAddrList.Add(ip.Address.ToString());
                }
            }
        }
    }
    return ipAddrList.ToArray();
}

이제이 함수는 특정 인터페이스 유형에 할당 된 모든 주소를 반환합니다. 이제 단일 문자열을 얻으려면 .FirstOrDefault()확장을 사용 하여 배열의 첫 번째 항목을 반환하거나 비어있는 경우 빈 문자열을 반환 할 수 있습니다.

GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault();


답변

다음은 나를 위해 일한 수정 된 버전 (compman2408의 버전)입니다.

    internal static string GetLocalIPv4(NetworkInterfaceType _type)
    {  // Checks your IP adress from the local network connected to a gateway. This to avoid issues with double network cards
        string output = "";  // default output
        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) // Iterate over each network interface
        {  // Find the network interface which has been provided in the arguments, break the loop if found
            if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
            {   // Fetch the properties of this adapter
                IPInterfaceProperties adapterProperties = item.GetIPProperties();
                // Check if the gateway adress exist, if not its most likley a virtual network or smth
                if (adapterProperties.GatewayAddresses.FirstOrDefault() != null)
                {   // Iterate over each available unicast adresses
                    foreach (UnicastIPAddressInformation ip in adapterProperties.UnicastAddresses)
                    {   // If the IP is a local IPv4 adress
                        if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {   // we got a match!
                            output = ip.Address.ToString();
                            break;  // break the loop!!
                        }
                    }
                }
            }
            // Check if we got a result if so break this method
            if (output != "") { break; }
        }
        // Return results
        return output;
    }

이 메소드를 다음과 같이 호출 할 수 있습니다.

GetLocalIPv4(NetworkInterfaceType.Ethernet);

변경 사항 : 게이트웨이 IP가 할당 된 어댑터에서 IP를 검색하고 있습니다. 두 번째 변경 사항 :이 방법을보다 효율적으로 만들기 위해 docstrings 및 break 문을 추가했습니다.


답변

이것은 VMWare 호스트 또는 기타 유효하지 않은 IP 주소를 피하면서 현재 IP를 얻는 가장 좋은 코드입니다.

public string GetLocalIpAddress()
{
    UnicastIPAddressInformation mostSuitableIp = null;

    var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

    foreach (var network in networkInterfaces)
    {
        if (network.OperationalStatus != OperationalStatus.Up)
            continue;

        var properties = network.GetIPProperties();

        if (properties.GatewayAddresses.Count == 0)
            continue;

        foreach (var address in properties.UnicastAddresses)
        {
            if (address.Address.AddressFamily != AddressFamily.InterNetwork)
                continue;

            if (IPAddress.IsLoopback(address.Address))
                continue;

            if (!address.IsDnsEligible)
            {
                if (mostSuitableIp == null)
                    mostSuitableIp = address;
                continue;
            }

            // The best IP is the IP got from DHCP server
            if (address.PrefixOrigin != PrefixOrigin.Dhcp)
            {
                if (mostSuitableIp == null || !mostSuitableIp.IsDnsEligible)
                    mostSuitableIp = address;
                continue;
            }

            return address.Address.ToString();
        }
    }

    return mostSuitableIp != null
        ? mostSuitableIp.Address.ToString()
        : "";
}


답변

LinQ를 사용하는 것이 더 쉽다고 생각합니다.

Dns.GetHostEntry(Dns.GetHostName())
   .AddressList
   .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
   .ToString()