Nhận địa chỉ IP cục bộ


301

Trong internet có một số nơi chỉ cho bạn cách lấy địa chỉ IP. Và rất nhiều trong số chúng trông giống như ví dụ này:

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();

Với ví dụ này tôi nhận được một số địa chỉ IP, nhưng tôi chỉ muốn lấy địa chỉ mà bộ định tuyến gán cho máy tính chạy chương trình: IP mà tôi sẽ cung cấp cho ai đó nếu anh ta muốn truy cập vào thư mục dùng chung trong máy tính của tôi ví dụ

Nếu tôi không được kết nối với mạng và tôi được kết nối trực tiếp qua internet qua modem không có bộ định tuyến thì tôi muốn gặp lỗi. Làm cách nào để biết máy tính của tôi có được kết nối với mạng bằng C # không và nếu có thì hãy lấy địa chỉ IP LAN.


If I am not connected to a network and I am connected to the internet Câu nói này có vẻ mâu thuẫn. Bạn đang cố gắng tìm hiểu xem máy tính của bạn có được kết nối với mạng LAN riêng hoặc Internet không?
Andy

4
Giống như một cảnh báo: Một máy tính có thể có nhiều giao diện IP, ví dụ như mạng LAN và WiFi. Nếu bạn liên kết một dịch vụ với một phần cứng cụ thể (ví dụ LAN), bạn cần IP của LAN. Hầu hết các ví dụ sau sẽ trả về địa chỉ IP "đầu tiên" hoặc "cuối cùng" được tìm thấy. Nếu bạn có nhiều hơn 2 địa chỉ IP, chương trình của bạn có thể hoạt động 50% thời gian, tùy thuộc vào thứ tự ngẫu nhiên mà HĐH trả về các địa chỉ IP.
Đánh dấu Lakata

@MarkLakata Tôi cũng nghĩ về vấn đề tương tự. Các chức năng trong câu trả lời của tôi dưới đây sẽ xử lý nó. Bạn có thể chỉ định loại giao diện mạng mà bạn muốn địa chỉ IP từ đó.
compman2408

3
Chỉ cần FTR, nếu bạn google ở ​​đây cho Unity3D, thì đó là Network.player.ipAddress trong API của họ
Fattie

@MarkLakata nói đúng, IP "đầu tiên" hoặc "cuối cùng" IP "chính xác", vì trình duyệt có thể sử dụng bất kỳ IP nào có sẵn. Có khả năng điều chỉnh tốt là trả về mọi IP được liên kết với máy.
UncaAlby

Câu trả lời:


457

Để lấy địa chỉ IP cục bộ:

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!");
}

Để kiểm tra xem bạn đã kết nối hay chưa:

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


29
sẽ không hoạt động nếu bạn sử dụng những thứ như hộp ảo vm, genymotion, v.v.
PauLEffect

5
Đồng ý với PaulEffect. Không chỉ phương pháp này là xấu cho nhiều card mạng, mà còn, nó không phân biệt giữa địa chỉ IP v6 và IP v4.
Tối đa

16
@John Địa chỉ gia đình.InterNetwork là IP v4 và Địa chỉ gia đình.InterNetworkV6 là IP v6
Leonardo Xavier

Tôi đang sử dụng Geraldo H Trả lời, nhưng nếu bất cứ ai đang sử dụng điều này, bạn có thể muốn xóa tất cả các ips kết thúc bằng 1, vì vậy nó sẽ xóa ips loopback và virtualbox / vmware
Leonardo Xavier

6
Có vẻ như bạn đang sử dụng VMWare hoặc phần mềm ảo hóa khác. OP đã không yêu cầu điều đó, vì vậy tôi nghĩ rằng việc bỏ phiếu do điều đó hơi khó khăn. Nếu bạn có VMWare hoặc nhiều NIC, một số câu trả lời khác đã cung cấp manh mối cho điều đó.
Ông trùm

218

Có một cách chính xác hơn khi có nhiều địa chỉ IP có sẵn trên máy cục bộ. Connectmột ổ cắm UDP và đọc điểm cuối cục bộ của nó:

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();
}

Connecttrên ổ cắm UDP có tác dụng như sau: nó đặt đích cho Send/ Recv, loại bỏ tất cả các gói từ các địa chỉ khác và - đó là những gì chúng ta sử dụng - chuyển ổ cắm sang trạng thái "được kết nối", cài đặt các trường thích hợp. Điều này bao gồm kiểm tra sự tồn tại của tuyến đến đích theo bảng định tuyến của hệ thống và đặt điểm cuối cục bộ tương ứng. Phần cuối dường như không có giấy tờ chính thức nhưng có vẻ như là một đặc điểm không thể thiếu của API ổ cắm Berkeley (tác dụng phụ của trạng thái "được kết nối" UDP) hoạt động đáng tin cậy trong cả Windows và Linux trên các phiên bản và phân phối.

Vì vậy, phương pháp này sẽ cung cấp địa chỉ cục bộ sẽ được sử dụng để kết nối với máy chủ từ xa được chỉ định. Không có kết nối thực sự được thiết lập, do đó ip từ xa được chỉ định có thể không truy cập được.


4
Đây là giải pháp tốt nhất phù hợp với nhu cầu của tôi. Trong tình huống của tôi, tôi có nhiều card mạng và một vài kết nối không dây. Tôi cần lấy địa chỉ IP ưa thích tùy thuộc vào kết nối nào được kích hoạt.
David

10
Không có kết nối mạng - dù sao bạn cũng không có địa chỉ IP. Do đó, mã vẫn giữ nguyên giá trị, mặc dù sẽ rất thận trọng khi thêm try..catch để xử lý tình huống như vậy và trả về một cái gì đó như "127.0.0.1" nếu một SocketException bị ném.
Nga

2
@PatrickSteele, vâng, nó trả về địa chỉ IP gửi đi ưa thích cho mục tiêu cụ thể. nếu bạn muốn lấy địa chỉ IP LAN của mình, hãy thử chỉ ra mục tiêu là một số ip từ mạng LAN của bạn
Mr.Wang từ Next Door

2
Phương pháp này hoạt động trên máy mac có lõi dotnet, trong khi câu trả lời được chấp nhận hiện không có.
Pellet

9
Giải pháp này hoạt động nhanh hơn khoảng 4 lần so với câu trả lời được chấp nhận (bởi Mrchief). Đây phải là câu trả lời thực sự
Kamarey

115

Tái cấu trúc mã của Mrcheif để tận dụng Linq (ví dụ .Net 3.0+). .

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);
}

:)


Tôi đã có một vài Địa chỉ IP là "Mạng liên kết", một giải pháp này thực sự hoạt động và trả lại đúng. Một cái khác từ Mrchief chỉ cho tôi cái cuối cùng. Vì vậy, thực sự cái này phải là cái đúng;)
Keenora Fluffball

26
@KeenoraFluffball - cái này cung cấp cho bạn cái đầu tiên, trong khi cái này cung cấp cho bạn cái cuối cùng (hoặc ngược lại, phụ thuộc vào cách danh sách được xây dựng). Dù bằng cách nào, cả hai đều không đúng - nếu có nhiều hơn 1 địa chỉ IP được cung cấp cho bạn, bạn cần biết bạn đang sử dụng mạng nào. Đoán bằng cách lấy đầu tiên hoặc cuối cùng không phải là giải pháp chính xác.
gbjbaanb

Cũng có thể muốn bao gồm
Địa chỉ gia đình.InterNetworkV6

trả về null nếu mạng không khả dụng là không hữu ích nếu bạn cũng phải xử lý các PC độc lập. Tôi đã thay thế nó bằng "return IPAddress.Loopback;" tương ứng với số IP đặc biệt 127.0.0.1.
Christian

109

Tôi biết điều này có thể đang đá một con ngựa chết, nhưng có lẽ điều này có thể giúp đỡ ai đó. Tôi đã tìm khắp nơi để tìm cách tìm địa chỉ IP cục bộ của mình, nhưng ở mọi nơi tôi thấy nó đều sử dụng:

Dns.GetHostEntry(Dns.GetHostName());

Tôi hoàn toàn không thích điều này vì nó chỉ nhận được tất cả các địa chỉ được gán cho máy tính của bạn. Nếu bạn có nhiều giao diện mạng (mà hầu như tất cả các máy tính đều làm bây giờ), bạn không biết địa chỉ nào đi với giao diện mạng nào. Sau khi thực hiện một loạt nghiên cứu, tôi đã tạo ra một hàm để sử dụng lớp NetworkInterface và lấy thông tin ra khỏi nó. Bằng cách này tôi có thể biết loại giao diện đó là gì (Ethernet, không dây, loopback, đường hầm, v.v.), cho dù nó có hoạt động hay không, và SOOO nhiều hơn nữa.

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;
}

Bây giờ để có được địa chỉ IPv4 của cuộc gọi giao diện mạng Ethernet của bạn:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

Hoặc giao diện Không dây của bạn:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

Nếu bạn cố gắng lấy địa chỉ IPv4 cho giao diện không dây, nhưng máy tính của bạn không cài đặt thẻ không dây, nó sẽ chỉ trả về một chuỗi trống. Điều tương tự với giao diện Ethernet.

Hy vọng điều này sẽ giúp được ai đó! :-)

BIÊN TẬP:

Nó đã được chỉ ra (cảm ơn @NasBanov) rằng mặc dù chức năng này giúp trích xuất địa chỉ IP theo cách tốt hơn nhiều so với việc sử dụng Dns.GetHostEntry(Dns.GetHostName())nó không hỗ trợ rất nhiều giao diện cùng loại hoặc nhiều địa chỉ IP trên một giao diện . Nó sẽ chỉ trả về một địa chỉ IP duy nhất khi có thể có nhiều địa chỉ được gán. Để trả về TẤT CẢ các địa chỉ được gán này, bạn có thể chỉ cần thao tác hàm ban đầu để luôn trả về một mảng thay vì một chuỗi. Ví dụ:

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();
}

Bây giờ chức năng này sẽ trả về TẤT CẢ các địa chỉ được gán cho một loại giao diện cụ thể. Bây giờ để chỉ lấy một chuỗi, bạn có thể sử dụng .FirstOrDefault()tiện ích mở rộng để trả về mục đầu tiên trong mảng hoặc, nếu nó trống, hãy trả về một chuỗi trống.

GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault();

5
Đây là một giải pháp tốt hơn vì không có khả năng sử dụng DNS ở nhiều nơi và giao diện có thể có nhiều địa chỉ IP. Tôi cũng sử dụng một phương pháp tương tự.
Mert Gülsoy

Vấn đề với điều này là bạn chỉ trả về 1 địa chỉ IP trên mỗi giao diện ... IP cuối cùng, foreach.
Nas Banov

@ compman2408 - không đúng, một giao diện có thể có nhiều IP, xem en.wikipedia.org/wiki/Multihoming#Variants cho tất cả các combo. Ví dụ rõ ràng là khi chạy cả IPv4 và IPv6, nhưng trong quá khứ tôi đã có bộ điều hợp ethernet duy nhất tham gia vào nhiều mạng IPv4. Có thể bất thường - nhưng hoàn toàn hợp pháp. Ví dụ: đối với Windows, hãy xem windowsnetworking.com/articles-tutorials/windows-2003/iêng
Nas Banov

@NasBanov Chức năng này chỉ được thiết lập để nhận địa chỉ IPv4 nên tôi thậm chí sẽ không nói về IPv6 và sự vô dụng hiện tại của nó. Tôi nhận thức được việc kết nối với nhiều mạng trên nhiều giao diện tuy nhiên chưa bao giờ nghe nói về việc kết nối với nhiều mạng trên cùng một giao diện. Mặc dù có vẻ như bạn đúng rằng điều đó thực sự có thể xảy ra, nhưng <1% số người sử dụng NIC của họ theo cách đó sẽ chỉ phải thay đổi hàm để trả về một mảng thay thế.
compman2408

1
Cảm ơn vì điều này. FYI, ít nhất là trên .NET 3.5 mono trên OSX item.OperationalStatusluôn trả về Unknown.
gman

36

Đây là phiên bản sửa đổi (từ phiên bản compman2408) hoạt động với tôi:

    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;
    }

Bạn có thể gọi phương thức này ví dụ như:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

Thay đổi: Tôi đang truy xuất IP từ bộ điều hợp có IP cổng được gán cho nó. Thay đổi thứ hai: Tôi đã thêm các tài liệu và tuyên bố phá vỡ để làm cho phương pháp này hiệu quả hơn.


2
Giải pháp thông minh. Bây giờ tôi đang sử dụng cái này.
RQDQ

4
Có cùng một vấn đề giống như mã mà nó được lấy từ: nó chỉ trả về một trong số các IP, một IP ngẫu nhiên từ nhiều người - không phải là mã bạn cần. Nó kiếm được ademiller.com/bloss/tech/2008/06/it-works-on-my-machine-award
Nas Banov

1
@NasBanov, Chắc chắn tôi đã kiếm được nó, như tôi đã nói trong bài viết của mình: "cái này hiệu quả với tôi". :-)
Gerardo H

Đây là con đường để đi, cảm ơn bạn vì điều này. Khi bạn đã cài đặt công tắc vòng lặp lại cho trình giả lập, tất cả các biến thể khác đều thất bại trong khi biến thể này thành công!
DiamondDrake

1
Tại sao bạn chỉ trả lại địa chỉ IP cuối cùng bạn đã tìm thấy, không phải địa chỉ đầu tiên? Một simpel breakở bên trong nhất ifhoặc returnsẽ làm điều đó.
Martin Mulder

20

Đây là mã tốt nhất tôi tìm thấy để lấy IP hiện tại, tránh nhận máy chủ VMWare hoặc địa chỉ IP không hợp lệ khác.

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()
        : "";
}

Bạn có lẽ nên giải thích, tại sao mã này là giải pháp cho câu trả lời. Bạn thực sự có thể nhận được câu trả lời cho câu hỏi nếu bạn kết nối với internet và điều này có gây ra lỗi không?
Philipp M

Các cách khác không sử dụng xác thực IsDnsEl đủ điều kiện và PrefixOrigin.
Rodcesar.santos

@PhilippM Nếu địa chỉ không phải là DNS Đủ điều kiện, thì đó là IP nội bộ dành riêng. Nó không phải là máy chủ cung cấp internet. Và nếu PrefixOrigin được cung cấp bởi máy chủ DHCP, thì đây có thể là lựa chọn địa chỉ tốt nhất. Đây là chức năng độc đáo hoạt động với tôi!
Rodcesar.santos

1
@ user1551843 - thật tuyệt, cảm ơn. Tôi đã sử dụng phương thức GethostByName cũ đã khấu hao nhưng nó đã trả lại IP của bộ điều hợp VMWare :)
Jason Newland

Đây là giải pháp duy nhất phù hợp với tôi trên vpn + không dây. Cảm ơn bạn.
jay-nguy hiểm

12

Tôi nghĩ rằng sử dụng LinQ dễ dàng hơn:

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

14
Đó không phải là LINQ, đó là phương pháp mở rộng và lambdas. Có một sự khác biệt.
Đánh dấu

10
@Mark - Nếu bạn không thêm "bằng System.Linq;" mặc dù vậy, bạn không thể sử dụng phương thức tiện ích mở rộng "Đầu tiên"
BornToCode

5
Đó là bởi vì phương thức mở rộng nằm trong lớp Enumerable nằm trong không gian tên System.Linq. Nó vẫn không phải là LINQ.
Đánh dấu

20
Đánh dấu, ngay cả ở dạng ngắn này, câu lệnh thực sự sử dụng cú pháp LINQ-to-object được trình bày với cú pháp phương thức (lambda). Cú pháp truy vấn chỉ đơn giản là đường cú pháp được biên dịch thành một chuỗi các lệnh gọi phương thức mở rộng IEnumerable, đó là những gì LINQ-to-object là. Nguồn: tác giả của một nhà cung cấp LINQ-to-SQL và một loạt các bài viết về chủ đề này.
hằng số g


9

Để cười, nghĩ rằng tôi sẽ thử và nhận một câu lệnh LINQ bằng cách sử dụng toán tử có điều kiện null C # 6 mới. Trông khá điên rồ và có thể không hiệu quả khủng khiếp, nhưng nó hoạt động.

private string GetLocalIPv4(NetworkInterfaceType type = NetworkInterfaceType.Ethernet)
{
    // Bastardized from: http://stackoverflow.com/a/28621250/2685650.

    return NetworkInterface
        .GetAllNetworkInterfaces()
        .FirstOrDefault(ni =>
            ni.NetworkInterfaceType == type
            && ni.OperationalStatus == OperationalStatus.Up
            && ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null
            && ni.GetIPProperties().UnicastAddresses.FirstOrDefault(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork) != null
        )
        ?.GetIPProperties()
        .UnicastAddresses
        .FirstOrDefault(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork)
        ?.Address
        ?.ToString()
        ?? string.Empty;
}

Logic lịch sự của Gerardo H(và bằng cách tham khảo compman2408).


Chắc chắn là rất vui (+1), nhưng thực sự không cần phải kém hiệu quả. Nhắc nhở tôi về lập trình trong LISP hoặc Forth :-)
Roland

6

Cách khác để nhận IP bằng biểu thức linq:

public static List<string> GetAllLocalIPv4(NetworkInterfaceType type)
{
    return NetworkInterface.GetAllNetworkInterfaces()
                   .Where(x => x.NetworkInterfaceType == type && x.OperationalStatus == OperationalStatus.Up)
                   .SelectMany(x => x.GetIPProperties().UnicastAddresses)
                   .Where(x => x.Address.AddressFamily == AddressFamily.InterNetwork)
                   .Select(x => x.Address.ToString())
                   .ToList();
}

5

@mrcheif Tôi đã tìm thấy câu trả lời này ngày hôm nay và nó rất hữu ích mặc dù nó đã trả về một IP sai (không phải do mã không hoạt động) nhưng nó đã cung cấp IP mạng liên kết sai khi bạn có những thứ như Himachi đang chạy.

public static string localIPAddress()
{
    IPHostEntry host;
    string localIP = "";
    host = Dns.GetHostEntry(Dns.GetHostName());

    foreach (IPAddress ip in host.AddressList)
    {
        localIP = ip.ToString();

        string[] temp = localIP.Split('.');

        if (ip.AddressFamily == AddressFamily.InterNetwork && temp[0] == "192")
        {
            break;
        }
        else
        {
            localIP = null;
        }
    }

    return localIP;
}

2
Ý bạn là Logmein Hamachi? Nó là một giải pháp VPN và nó tinker với ngăn xếp mạng. Ngoài ra, là một VPN, có vẻ hợp lý khi nó trả về IP được gán VPN khi được kết nối (chỉ là phỏng đoán của tôi).
Ông trùm

2
Hoàn toàn không đáng tin cậy. Không chỉ 192.0.0.0/8không phải là một thử nghiệm chính xác cho một địa chỉ IP riêng (có 3 phạm vi, tất cả đều khác với địa chỉ này), nó cũng có thể là một phạm vi mạng công ty, do đó không quá "cục bộ".
ivan_pozdeev

5

Đã thử nghiệm với một hoặc nhiều thẻ LAN và máy ảo

public static string DisplayIPAddresses()
    {
        string returnAddress = String.Empty;

        // Get a list of all network interfaces (usually one per network card, dialup, and VPN connection)
        NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

        foreach (NetworkInterface network in networkInterfaces)
        {
            // Read the IP configuration for each network
            IPInterfaceProperties properties = network.GetIPProperties();

            if (network.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                   network.OperationalStatus == OperationalStatus.Up &&
                   !network.Description.ToLower().Contains("virtual") &&
                   !network.Description.ToLower().Contains("pseudo"))
            {
                // Each network interface may have multiple IP addresses
                foreach (IPAddressInformation address in properties.UnicastAddresses)
                {
                    // We're only interested in IPv4 addresses for now
                    if (address.Address.AddressFamily != AddressFamily.InterNetwork)
                        continue;

                    // Ignore loopback addresses (e.g., 127.0.0.1)
                    if (IPAddress.IsLoopback(address.Address))
                        continue;

                    returnAddress = address.Address.ToString();
                    Console.WriteLine(address.Address.ToString() + " (" + network.Name + " - " + network.Description + ")");
                }
            }
        }

       return returnAddress;
    }

Hãy nhớ rằng cái này chỉ hoạt động cho Ethernet. Xóa giới hạn NetworkInterfaceType để hỗ trợ wi-fi.
scor4er

3

Chỉ là một phiên bản cập nhật của tôi bằng LINQ:

/// <summary>
/// Gets the local Ipv4.
/// </summary>
/// <returns>The local Ipv4.</returns>
/// <param name="networkInterfaceType">Network interface type.</param>
IPAddress GetLocalIPv4(NetworkInterfaceType networkInterfaceType)
{
    var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.NetworkInterfaceType == networkInterfaceType && i.OperationalStatus == OperationalStatus.Up);

    foreach (var networkInterface in networkInterfaces)
    {
        var adapterProperties = networkInterface.GetIPProperties();

        if (adapterProperties.GatewayAddresses.FirstOrDefault() == null)
                continue;
        foreach (var ip in networkInterface.GetIPProperties().UnicastAddresses)
        {
            if (ip.Address.AddressFamily != AddressFamily.InterNetwork)
                    continue;

            return ip.Address;
        }
    }

    return null;
}

2

Điều kiện tiên quyết: bạn phải thêm tham chiếu System.Data.Linq và tham chiếu nó

using System.Linq;
string ipAddress ="";
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
ipAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork));

2

Tôi cũng đang vật lộn để có được IP chính xác.

Tôi đã thử một loạt các giải pháp ở đây nhưng không có giải pháp nào cung cấp cho tôi ảnh hưởng mong muốn. Hầu như tất cả các bài kiểm tra có điều kiện được cung cấp khiến không có địa chỉ được sử dụng.

Đây là những gì làm việc cho tôi, hy vọng nó sẽ giúp ...

var firstAddress = (from address in NetworkInterface.GetAllNetworkInterfaces().Select(x => x.GetIPProperties()).SelectMany(x => x.UnicastAddresses).Select(x => x.Address)
                    where !IPAddress.IsLoopback(address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
                    select address).FirstOrDefault();

Console.WriteLine(firstAddress);

1
string str="";

System.Net.Dns.GetHostName();

IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(str);

IPAddress[] addr = ipEntry.AddressList;

string IP="Your Ip Address Is :->"+ addr[addr.Length - 1].ToString();

str luôn trống
aj.toulan

1

Hãy nhớ rằng, trong trường hợp chung, bạn có thể có nhiều bản dịch NAT đang diễn ra và nhiều máy chủ dns, mỗi máy chủ hoạt động ở các cấp độ dịch NAT khác nhau.

Điều gì sẽ xảy ra nếu bạn có NAT của nhà mạng và muốn liên lạc với các khách hàng khác của cùng một nhà mạng? Trong trường hợp chung, bạn không bao giờ biết chắc chắn vì bạn có thể xuất hiện với các tên máy chủ khác nhau ở mỗi bản dịch NAT.


1

Đã lỗi thời, điều này làm việc với tôi

public static IPAddress GetIPAddress()
{ 
 IPAddress ip = Dns.GetHostAddresses(Dns.GetHostName()).Where(address => 
 address.AddressFamily == AddressFamily.InterNetwork).First();
 return ip;
}

1

Cập nhật câu trả lời của Mrchief với Linq, chúng tôi sẽ có:

public static IPAddress GetLocalIPAddress()
{
   var host = Dns.GetHostEntry(Dns.GetHostName());
   var ipAddress= host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
   return ipAddress;
}

1

Điều này trả về địa chỉ từ bất kỳ giao diện nào có địa chỉ cổng và địa chỉ unicast trong hai danh sách riêng biệt, IPV4 và IPV6.

public static (List<IPAddress> V4, List<IPAddress> V6) GetLocal()
{
    List<IPAddress> foundV4 = new List<IPAddress>();
    List<IPAddress> foundV6 = new List<IPAddress>();

    NetworkInterface.GetAllNetworkInterfaces().ToList().ForEach(ni =>
    {
        if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null)
        {
            ni.GetIPProperties().UnicastAddresses.ToList().ForEach(ua =>
            {
                if (ua.Address.AddressFamily == AddressFamily.InterNetwork) foundV4.Add(ua.Address);
                if (ua.Address.AddressFamily == AddressFamily.InterNetworkV6) foundV6.Add(ua.Address);
            });
        }
    });

    return (foundV4.Distinct().ToList(), foundV6.Distinct().ToList());
}

Giải pháp gọn gàng :)
Johan Franzén

1

Đã có nhiều câu trả lời, nhưng tôi vẫn đóng góp cho tôi một câu:

public static IPAddress LocalIpAddress() {
    Func<IPAddress, bool> localIpPredicate = ip =>
        ip.AddressFamily == AddressFamily.InterNetwork &&
        ip.ToString().StartsWith("192.168"); //check only for 16-bit block
    return Dns.GetHostEntry(Dns.GetHostName()).AddressList.LastOrDefault(localIpPredicate);
}

Lót:

public static IPAddress LocalIpAddress() => Dns.GetHostEntry(Dns.GetHostName()).AddressList.LastOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork && ip.ToString().StartsWith("192.168"));

lưu ý: Tìm kiếm từ cuối cùng vì nó vẫn hoạt động sau khi một số giao diện được thêm vào thiết bị, chẳng hạn như MobileHotspot, VPN hoặc các bộ điều hợp ảo ưa thích khác.


1
Vì vậy, nếu IP cục bộ của tôi là 10.0.2.3 thì không tìm thấy? Điều đó thực sự kỳ lạ trong mã này.
thân

@frankhommers được cho biết chỉ kiểm tra khối 16 bit
nyconing

Các khối 16 bit cũng có thể là một cái gì đó khác hơn 192.168
frankhommers

0

Ngoài ra, chỉ cần mã đơn giản để nhận Ip khách hàng:

        public static string getclientIP()
        {
            var HostIP = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
            return HostIP;
        }

Hy vọng nó sẽ giúp bạn.


0
Dns.GetHostEntry(Dns.GetHostName()).AddressList[1].MapToIPv4() //returns 192.168.14.1

nhập mô tả hình ảnh ở đây


5
Câu trả lời của bạn nên chứa một mô tả về cách thức hoạt động của nó đối với trường hợp của OP và cho cả những người đọc trong tương lai.
Ronak Dhoot

Tốt hơn là bao gồm một lời giải thích về câu trả lời của bạn cho độc giả trong tương lai.
Nicolas Gervais

0

Mã compman2408 đã sửa đổi để có thể lặp qua từng mã NetworkInterfaceType.

public static string GetLocalIPv4 (NetworkInterfaceType _type) {
    string output = null;
    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;
}

Và bạn có thể gọi nó như vậy:

static void Main (string[] args) {
    // Get all possible enum values:
    var nitVals = Enum.GetValues (typeof (NetworkInterfaceType)).Cast<NetworkInterfaceType> ();

    foreach (var nitVal in nitVals) {
        Console.WriteLine ($"{nitVal} => {GetLocalIPv4 (nitVal) ?? "NULL"}");
    }
}

0
Imports System.Net
Imports System.Net.Sockets
Function LocalIP()
    Dim strHostName = Dns.GetHostName
    Dim Host = Dns.GetHostEntry(strHostName)
    For Each ip In Host.AddressList
        If ip.AddressFamily = AddressFamily.InterNetwork Then
            txtIP.Text = ip.ToString
        End If
    Next

    Return True
End Function

Dưới đây hành động tương tự

Hàm LocalIP ()

Dim Host As String = Dns.GethostEntry (Dns.GethostName) .AddressList (1) .MapToIPv4.ToString

txtIP.Text = Máy chủ

Trả về đúng

Chức năng kết thúc


Ví dụ bên dưới là hành động tương tự Hàm LocalIP () Dim Host As String = Dns.GethostEntry (Dns.GethostName) .AddressList (1) .MapToIPv4.ToString txtIP.Text = Host Trả về Hàm kết thúc đúng
YongJae Kim

-2
Dns.GetHostEntry(Dns.GetHostName()).AddressList[1]

một dòng mã: D


7
Nó có thể ném OutOfRangeException trong một số trường hợp.
Lâu đài

5
Ngoài ra, làm thế nào để bạn biết cái nào bạn muốn? Điều gì đúng cho bạn có thể sai đối với người khác.
Đánh dấu

-3

Nếu bạn có máy ảo hoặc thẻ mạng phụ, có thể có các giá trị khác trong danh sách địa chỉ. Đề nghị của tôi là kiểm tra các mục trong danh sách địa chỉ và in phù hợp. Trong trường hợp của tôi, mục 3 là địa chỉ ipv4 của máy tôi

IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[3];
string ip = ipAddr.ToString();

Đừng quên thêm using System.Net;


1
Điều chỉnh; TẤT CẢ chúng là địa chỉ IP của máy của bạn. Mà bạn muốn, tuy nhiên, là một câu chuyện hoàn toàn khác. Lưu ý rằng thứ tự có thể thay đổi và do phương thức bạn đang sử dụng, bạn sẽ luôn đoán được.
Đánh dấu

Đó là những gì tôi đã nói, bạn nên kiểm tra các mục trong danh sách địa chỉ, và vâng nó đoán, nhưng sau khi xem tất cả các mục, việc đoán không khó lắm
Bibaswann Bandyopadhyay

Làm thế nào bạn biết cái nào phù hợp? Sử dụng giải pháp của compman2048, ít nhất bạn sẽ biết cái nào được gắn với giao diện nào.
Đánh dấu

Giải pháp đó không hoạt động trong máy tính của tôi, vì tôi có 2 giao diện wlan, 2 máy ảo và 1 trình giả lập, vì vậy tôi nhận được rất nhiều IP. Nhưng nếu bạn đang tìm kiếm địa chỉ nội bộ được cung cấp bởi bộ định tuyến thì nó sẽ bắt đầu bằng 192 hoặc 172 hoặc 10, đó là cách tôi hiểu
Bibaswann Bandyopadhyay

Trừ khi bộ định tuyến của bạn cung cấp IP công cộng, điều này không phổ biến nhưng có thể.
Đánh dấu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.