รับที่อยู่ IP ท้องถิ่น


301

ในอินเทอร์เน็ตมีหลายแห่งที่แสดงวิธีรับที่อยู่ 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 # และถ้าเป็นเช่นนั้นเพื่อรับที่อยู่ IP ของ LAN


If I am not connected to a network and I am connected to the internet คำสั่งนี้ดูเหมือนจะขัดแย้งกัน คุณพยายามคิดหรือไม่ว่าคอมพิวเตอร์ของคุณเชื่อมต่อกับ LAN ส่วนตัวหรืออินเทอร์เน็ต?
Andy

4
เช่นเดียวกับคำเตือน: คอมพิวเตอร์สามารถมีมากกว่าหนึ่งอินเทอร์เฟซ IP ตัวอย่างเช่น LAN และ WiFi หากคุณผูกบริการกับฮาร์ดแวร์ชิ้นใดชิ้นหนึ่ง (เช่น LAN) คุณต้องใช้ IP ของ LAN ตัวอย่างต่อไปนี้ส่วนใหญ่จะส่งคืนที่อยู่ IP "แรก" หรือ "ล่าสุด" หากคุณมีที่อยู่ IP มากกว่า 2 รายการโปรแกรมของคุณอาจทำงานได้ 50% ของเวลาทั้งนี้ขึ้นอยู่กับลำดับการสุ่มที่ระบบปฏิบัติการจะส่งคืนที่อยู่ IP
Mark Lakata

@ MarkLakata ฉันคิดเรื่องเดียวกัน ฟังก์ชั่นในคำตอบของฉันด้านล่างจะจัดการกับมัน คุณสามารถระบุประเภทของอินเทอร์เฟซเครือข่ายที่คุณต้องการที่อยู่ IP จาก
compman2408

3
เพียงแค่ FTR ถ้าคุณอยู่ที่นี่เพื่อ Unity3D นั่นคือ Network.player.ip ที่อยู่ใน API ของพวกเขา
Fattie

@MarkLakata พูดอย่างเคร่งครัด IP "ครั้งแรก" หรือ "ล่าสุด" คือ IP "ถูกต้อง" เนื่องจากเบราว์เซอร์อาจใช้ IP ใด ๆ ที่มีอยู่ การแก้ไขที่ดีน่าจะคืนค่าIP ทุกอันที่เกี่ยวข้องกับเครื่อง
UncaAlby

คำตอบ:


457

วิธีรับที่อยู่ 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();


29
จะไม่ทำงานหากคุณใช้สิ่งต่าง ๆ เช่นกล่องเสมือน vm, จีโนมและอื่น ๆ
PauLEffect

5
เห็นด้วยกับ PaulEffect ไม่เพียง แต่วิธีการนี้จะไม่ดีสำหรับการ์ดเครือข่ายหลายใบ แต่ก็ไม่แตกต่างกันระหว่างที่อยู่ IP v6 และที่อยู่ IP v4
Max

16
@John AddressFamily.InterNetwork คือ IP v4 และ AddressFamily.InterNetworkV6 คือ IP v6
Leonardo Xavier

ฉันกำลังใช้ Geraldo H คำตอบ แต่ถ้าใครใช้นี่คุณอาจต้องการลบ ips ทั้งหมดที่ลงท้ายด้วย 1 ดังนั้นมันจะลบลูปแบ็คและ virtualbox / vmware ค่าเริ่มต้น ips
Leonardo Xavier

6
ดูเหมือนว่าคุณกำลังใช้ VMWare หรือซอฟต์แวร์การจำลองเสมือนอื่น ๆ OP ไม่ได้ขอสิ่งนั้นดังนั้นฉันจึงคิดว่าการลงคะแนนเสียงเนื่องจากมันค่อนข้างรุนแรง หากคุณมี VMWare หรือ NIC หลายรายการคำตอบอื่น ๆ จะให้เบาะแสไปแล้ว
Mrchief

218

มีวิธีที่แม่นยำยิ่งขึ้นเมื่อมีที่อยู่หลาย IP พร้อมใช้งานในเครื่องท้องถิ่น Connectซ็อกเก็ต UDP และอ่านจุดปลายเฉพาะที่:

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

Connectบนซ็อกเก็ต UDP มีผลดังต่อไปนี้: มันกำหนดปลายทางสำหรับSend/ Recvทิ้งแพ็กเก็ตทั้งหมดจากที่อยู่อื่นและ - ซึ่งเป็นสิ่งที่เราใช้ - ถ่ายโอนซ็อกเก็ตเข้าสู่สถานะ "เชื่อมต่อ" ตั้งค่าฟิลด์ที่เหมาะสม ซึ่งรวมถึงการตรวจสอบการมีอยู่ของเส้นทางไปยังปลายทางตามตารางเส้นทางของระบบและการตั้งค่าจุดสิ้นสุดภายในเครื่องให้สอดคล้องกัน ส่วนสุดท้ายดูเหมือนว่าจะไม่มีเอกสารอย่างเป็นทางการ แต่ดูเหมือนว่าลักษณะสำคัญของBerkeley sockets API (ผลข้างเคียงของสถานะ "เชื่อมต่อ" ของ UDP) ที่ทำงานได้อย่างน่าเชื่อถือทั้งใน Windows และ Linuxในเวอร์ชันและการแจกแจง

ดังนั้นวิธีนี้จะให้ที่อยู่ในท้องถิ่นที่จะใช้ในการเชื่อมต่อกับโฮสต์ระยะไกลที่ระบุ ไม่มีการเชื่อมต่อจริงที่สร้างขึ้นดังนั้น IP ระยะไกลที่ระบุจึงไม่สามารถเข้าถึงได้


4
นี่เป็นทางออกที่ดีที่สุดที่เหมาะกับความต้องการของฉัน ในสถานการณ์ของฉันฉันมีการ์ดเครือข่ายมากมายและการเชื่อมต่อไร้สายเล็กน้อย ฉันต้องได้รับที่อยู่ IP ที่ต้องการทั้งนี้ขึ้นอยู่กับการเชื่อมต่อที่เปิดใช้งาน
เดวิด

10
หากไม่มีการเชื่อมต่อเครือข่าย - คุณไม่มีที่อยู่ IP แต่อย่างใด ดังนั้นรหัสยังคงถูกต้องแม้ว่าจะระมัดระวังในการเพิ่มลอง .. จับเพื่อจัดการกับสถานการณ์ดังกล่าวและส่งคืนบางสิ่งเช่น "127.0.0.1" ถ้ามีการโยน SocketException
รัส

2
@PatrickSteele ใช่แล้วมันจะส่งคืนที่อยู่ IP ขาออกที่ต้องการสำหรับเป้าหมายเฉพาะ หากคุณต้องการได้รับที่อยู่ IP ของ LAN ให้ลองระบุเป้าหมายให้เป็น IP บางส่วนจาก LAN ของคุณ
Mr.Wang จาก Next Door

2
วิธีนี้ใช้ได้กับ mac ที่มี dotnet core ในขณะที่คำตอบที่ยอมรับไม่ได้
Pellet

9
วิธีนี้ใช้ได้ผลเร็วกว่าคำตอบที่ยอมรับ (โดย Mrchief) ประมาณ 4 เท่า นี่ควรเป็นคำตอบที่แท้จริง
Kamarey

115

Refactoring code ของ Mrcheif เพื่อใช้ประโยชน์จาก Linq (เช่น. 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);
}

:)


ฉันมีที่อยู่ IP สองสามรายการเป็น "Inter Network" โซลูชันนี้ใช้งานได้จริงและให้ผลตอบแทนที่เหมาะสม อีกอันจาก Mrchief เพิ่งมอบอันสุดท้ายให้ฉัน ดังนั้นอันที่จริงอันนี้ควรเป็นอันที่เหมาะสม;)
Keenora Fluffball

26
@KeenoraFluffball - อันนี้ให้อันแรกกับคุณในขณะที่อันนี้ให้อันสุดท้ายแก่คุณ (หรือในทางกลับกันขึ้นอยู่กับการสร้างรายการ) ไม่ว่าจะด้วยวิธีใดไม่ถูกต้อง - หากมีที่อยู่ IP ให้คุณมากกว่า 1 คุณต้องทราบว่าคุณใช้เครือข่ายใด การเดาโดยการใช้ครั้งแรกหรือครั้งสุดท้ายไม่ใช่วิธีที่ถูกต้อง
gbjbaanb

อาจต้องการรวม AddressFamily.InterNetworkV6
joelsand

การคืนค่าเป็นโมฆะหากเครือข่ายไม่พร้อมใช้งานจะไม่มีประโยชน์หากคุณต้องจัดการพีซีแบบสแตนด์อโลนเช่นกัน ฉันแทนที่ด้วย "return IPAddress.Loopback;" ซึ่งสอดคล้องกับหมายเลข IP พิเศษ 127.0.0.1
คริสเตียน

109

ฉันรู้ว่านี่อาจเป็นการเตะม้าที่ตายแล้ว แต่นี่อาจช่วยคนได้ ฉันดูทั่วสถานที่เพื่อหาที่อยู่ IP ในพื้นที่ของฉัน แต่ทุกที่ที่ฉันพบจะบอกว่าให้ใช้:

Dns.GetHostEntry(Dns.GetHostName());

ฉันไม่ชอบสิ่งนี้เลยเพราะเพิ่งได้รับที่อยู่ทั้งหมดที่กำหนดให้กับคอมพิวเตอร์ของคุณ หากคุณมีอินเตอร์เฟซเครือข่ายหลายตัว (ซึ่งคอมพิวเตอร์เกือบทุกเครื่องใช้งานได้แล้ววันนี้) คุณไม่มีความคิดใดว่าที่อยู่จะไปกับอินเทอร์เฟซเครือข่ายใด หลังจากทำการค้นคว้ามากมายฉันได้สร้างฟังก์ชันเพื่อใช้คลาส NetworkInterface และดึงข้อมูลออกมา ด้วยวิธีนี้ฉันสามารถบอกได้ว่ามันเป็นอินเทอร์เฟซประเภทใด (อีเธอร์เน็ตไร้สายลูปแบ็คอุโมงค์ ฯลฯ ) ไม่ว่าจะใช้งานอยู่หรือไม่และ SOOO อื่น ๆ อีกมากมาย

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 ของการโทรติดต่อเครือข่าย Ethernet:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

หรืออินเตอร์เฟซไร้สายของคุณ:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

หากคุณพยายามรับที่อยู่ IPv4 สำหรับอินเทอร์เฟซแบบไร้สาย แต่คอมพิวเตอร์ของคุณไม่มีการ์ดไร้สายติดตั้งอยู่ก็จะส่งคืนสตริงว่างเปล่า สิ่งเดียวกันกับอินเตอร์เฟสอีเธอร์เน็ต

หวังว่านี่จะช่วยใครซักคน! :-)

แก้ไข:

มันชี้ให้เห็น (ขอบคุณ @NasBanov) ว่าถึงแม้ว่าฟังก์ชั่นนี้จะเกี่ยวกับการดึงที่อยู่ IP ในทางที่ดีกว่าการใช้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();

5
นี่เป็นวิธีที่ดีกว่าเนื่องจากไม่มีการใช้งาน DNS ในสถานที่และอินเทอร์เฟซจำนวนมากสามารถมีที่อยู่ IP หลายแห่ง ฉันยังใช้วิธีการที่คล้ายกัน
Mert Gülsoy

ปัญหานี้คือคุณคืนค่าที่อยู่ IP 1 รายการต่อหนึ่งอินเทอร์เฟซ ... IP สุดท้ายเท่านั้น
Nas Banov

@ compman2408 - ไม่จริงอินเทอร์เฟซเดียวสามารถมีได้หลาย IP ดูen.wikipedia.org/wiki/Multihoming#Variantsสำหรับคอมโบทั้งหมด ตัวอย่างที่ชัดเจนคือเมื่อทำงานทั้ง IPv4 และ IPv6 แต่ในอดีตที่ผ่านมาฉันมีอะแดปเตอร์อีเธอร์เน็ตเดียวเข้าร่วมในเครือข่าย IPv4 หลายเครือข่าย อาจผิดปกติ - แต่ถูกกฎหมายอย่างสมบูรณ์ ตัวอย่างสำหรับ Windows ดูwindowsnetworking.com/articles-tutorials/windows-2003/…
Nas Banov

@NasBanov ฟังก์ชั่นนี้ตั้งขึ้นเพื่อรับที่อยู่ IPv4 เท่านั้นดังนั้นฉันจะไม่พูดถึง IPv6 และความไร้ประโยชน์ปัจจุบันของมัน ฉันทราบว่าการเชื่อมต่อหลายเครือข่ายกับหลายเครือข่ายในหลาย ๆ อินเทอร์เฟซ แต่ไม่เคยได้ยินการเชื่อมต่อกับเครือข่ายหลาย ๆ อินเทอร์เฟซเดียวกัน แม้ว่าดูเหมือนว่าคุณจะถูกต้องว่าเป็นไปได้จริง <1% ของผู้ใช้ NIC ของพวกเขาด้วยวิธีที่จะต้องเปลี่ยนฟังก์ชั่นเพื่อส่งกลับอาร์เรย์แทน
compman2408

1
ขอบคุณสำหรับสิ่งนี้. FYI อย่างน้อยใน NET 3.5 โมโนใน OSX ผลตอบแทนเสมอitem.OperationalStatus Unknown
gman

36

นี่คือรุ่นที่แก้ไข (จากของ 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 ที่กำหนดไว้ การเปลี่ยนแปลงที่สอง: ฉันได้เพิ่มเอกสารและคำสั่งแบ่งเพื่อทำให้วิธีนี้มีประสิทธิภาพมากขึ้น


2
ทางออกที่ฉลาด ตอนนี้ฉันใช้สิ่งนี้
RQDQ

4
มีปัญหาเดียวกันเช่นรหัสที่ได้รับมาจาก: มันแค่คืนค่า IP หนึ่งรายการซึ่งเป็น IP แบบสุ่มจากหลาย ๆ อันซึ่งไม่จำเป็นต้องเป็นรหัสที่คุณต้องการ มันได้รับademiller.com/blogs/tech/2008/06/it-works-on-my-machine-award
Nas Banov

1
@NasBanov แน่นอนว่าฉันได้รับมันเพราะฉันระบุในโพสต์ของฉัน: "ซึ่งทำงานให้ฉัน" :-)
Gerardo H

นี่คือวิธีที่จะไปขอบคุณสำหรับสิ่งนี้ เมื่อคุณมีสวิตช์วนกลับสำหรับการติดตั้งอีมูเลเตอร์ตัวแปรอื่น ๆ ทั้งหมดจะล้มเหลวในขณะที่สวิตช์ตัวนี้ทำสำเร็จ!
DiamondDrake

1
ทำไมคุณส่งคืนที่อยู่ IP ล่าสุดที่คุณพบไม่ใช่ครั้งแรก SIMPEL breakในส่วนใหญ่ifหรือreturnจะทำเคล็ดลับ
Martin Mulder

20

นี่เป็นรหัสที่ดีที่สุดที่ฉันพบเพื่อรับ IP ปัจจุบันหลีกเลี่ยงการรับโฮสต์ VMWare หรือที่อยู่ 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()
        : "";
}

คุณควรจะอธิบายว่าทำไมรหัสนี้เป็นคำตอบสำหรับคำตอบ คุณสามารถรับคำตอบของคำถามได้หรือไม่หากคุณเชื่อมต่อกับอินเทอร์เน็ตและสิ่งนี้ส่งผลให้เกิดข้อผิดพลาดหรือไม่?
Philipp M

วิธีอื่น ๆ ไม่ใช้การตรวจสอบ IsDnsEligible และ PrefixOrigin
rodcesar.santos

@PhilippM หากที่อยู่ไม่ใช่ DNS ที่มีสิทธิ์แสดงว่าเป็น IP ภายในที่สงวนไว้ ไม่ใช่โฮสต์ของผู้ให้บริการอินเทอร์เน็ต และถ้า PrefixOrigin ถูกจัดหาโดยเซิร์ฟเวอร์ DHCP ความเป็นไปได้นี่คือตัวเลือกที่อยู่ที่ดีที่สุด นี่คือฟังก์ชั่นพิเศษที่ใช้งานได้สำหรับฉัน!
rodcesar.santos

1
@ user1551843 - เยี่ยมมากขอบคุณ ผมใช้วิธีการตัดค่าเสื่อมราคา gethostbyname เก่า แต่มันก็กลับ IP ของอะแดปเตอร์ VMWare :)
เจสันนิวแลนด์

นี่เป็นทางออกเดียวที่ทำงานสำหรับฉันใน vpn + ไร้สาย ขอบคุณ.
jay-danger

12

ฉันคิดว่าการใช้ LinQ ง่ายกว่า:

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

14
นั่นไม่ใช่ LINQ นั่นเป็นวิธีการขยายและ lambdas มีความแตกต่าง
ทำเครื่องหมาย

10
@ Mark - หากคุณไม่เพิ่ม "using System.Linq;" คุณไม่สามารถใช้วิธีการขยาย "ครั้งแรก" ได้
BornToCode

5
นั่นเป็นเพราะวิธีการขยายอยู่ในระดับ Enumerable ซึ่งอยู่ใน System.Linq namespace มันยังไม่เป็น LINQ
Mark

20
ทำเครื่องหมายแม้ในรูปแบบย่อนี้คำสั่งนั้นแน่นอนโดยใช้ LINQ-to-objects ที่นำเสนอด้วยไวยากรณ์ (lambda) ไวยากรณ์ Query syntax เป็นเพียงน้ำตาล syntactic ที่ได้รับการคอมไพล์ไปยังเชนของการเรียกเมธอดการขยาย IEnumerable ซึ่งเป็นสิ่งที่ LINQ-to-objects แหล่งที่มา: เขียนผู้ให้บริการ LINQ-to-SQL และชุดบทความในหัวข้อ
Constantine g


9

สำหรับเสียงหัวเราะคิดว่าฉันจะลองและได้รับข้อความสั่ง LINQ เดียวโดยใช้ตัวดำเนินการ null แบบไม่มีเงื่อนไข C # 6 ใหม่ ดูบ้าสวยและอาจไม่มีประสิทธิภาพอย่างน่ากลัว แต่ก็ใช้งานได้

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

ตรรกะมารยาทของGerardo H(และโดยการอ้างอิงcompman2408)


สนุกแน่นอน (+1) แต่จริงๆแล้วไม่จำเป็นต้องไร้ประสิทธิภาพเลย เตือนฉันเกี่ยวกับการเขียนโปรแกรมใน LISP หรือ Forth :-)
Roland

6

วิธีอื่นในการรับ IP โดยใช้ linq expression:

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 ฉันพบคำตอบนี้วันนี้และมันมีประโยชน์มากแม้ว่ามันจะส่งคืน IP ที่ไม่ถูกต้อง (ไม่ใช่เพราะรหัสไม่ทำงาน) แต่มันให้ IP internetwork ที่ไม่ถูกต้องเมื่อคุณมีสิ่งต่าง ๆ เช่น Himachi ทำงานอยู่

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
คุณหมายถึง Logmein Hamachi หรือเปล่า มันเป็นโซลูชัน VPN และจัดการกับเครือข่ายสแต็ค นอกจากนี้การเป็น VPN ก็ดูเหมือนว่ามันจะส่งคืน IP ที่ได้รับมอบหมาย VPN เมื่อเชื่อมต่อ
Mrchief

2
ไม่น่าเชื่อถืออย่างสมบูรณ์ ไม่เพียง แต่192.0.0.0/8เป็นการทดสอบที่ไม่ถูกต้องสำหรับที่อยู่ IP ส่วนตัว (มี 3 ช่วงซึ่งแตกต่างจากที่อยู่นี้) อาจเป็นช่วงเครือข่ายขององค์กรได้ดังนั้นจึงไม่ "ท้องถิ่น" มากนัก
ivan_pozdeev

5

ทดสอบกับการ์ด LAN หนึ่งหรือหลายการ์ดและเครื่องเสมือน

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

โปรดทราบว่าอันนี้ใช้งานได้กับอีเทอร์เน็ตเท่านั้น ลบข้อ จำกัด NetworkInterfaceType เพื่อรองรับ Wi-Fi
scor4er

3

เป็นเพียงเหมืองรุ่นปรับปรุงโดยใช้ 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

สิ่งที่ต้องมีก่อน: คุณต้องเพิ่มการอ้างอิง System.Data.Linq และอ้างอิง

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

2

ฉันยังดิ้นรนกับการได้รับ IP ที่ถูกต้อง

ฉันลองใช้วิธีแก้ไขปัญหาต่าง ๆ ที่นี่ แต่ไม่มีใครให้ผลที่ฉันต้องการ การทดสอบตามเงื่อนไขเกือบทั้งหมดที่ให้ไว้ไม่ได้ใช้ที่อยู่

นี่คือสิ่งที่ใช้ได้ผลสำหรับฉันหวังว่ามันจะช่วย ...

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 ว่างเปล่าเสมอ
aj.toulan

1

โปรดทราบว่าในกรณีทั่วไปคุณอาจมีการแปล NAT หลายรายการเกิดขึ้นและเซิร์ฟเวอร์ dns หลายเครื่องแต่ละเครื่องจะทำงานในระดับการแปล NAT ที่แตกต่างกัน

ถ้าคุณมีเกรด NAT ของผู้ให้บริการและต้องการสื่อสารกับลูกค้ารายอื่นของผู้ให้บริการรายเดียวกัน ในกรณีทั่วไปคุณไม่เคยรู้แน่ชัดเพราะคุณอาจปรากฏชื่อโฮสต์ที่ต่างกันในการแปล NAT ทุกครั้ง


1

ล้าสมัยไปแล้วสิ่งนี้ใช้ได้กับฉัน

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

1

อัปเดตคำตอบของ Mrchief กับ Linq เราจะได้:

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

1

ส่งคืนที่อยู่จากอินเทอร์เฟซใด ๆ ที่มีที่อยู่เกตเวย์และที่อยู่แบบ unicast ในรายการที่แยกกันสองรายการคือ IPV4 และ 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());
}

วิธีแก้ปัญหาเรียบร้อย :)
Johan Franzén

1

มีคำตอบมากมายอยู่แล้ว แต่ฉันยังคงให้การสนับสนุนฉัน:

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

หนึ่งในสายการบิน:

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

หมายเหตุ: ค้นหาล่าสุดเพราะมันยังคงทำงานหลังจากอินเทอร์เฟซบางอย่างถูกเพิ่มเข้าไปในอุปกรณ์เช่น MobileHotspot, VPN หรืออะแดปเตอร์เสมือนแฟนซีอื่น ๆ


1
ดังนั้นหาก IP ท้องถิ่นของฉันคือ 10.0.2.3 ไม่พบ? มันแปลกมากในรหัสนี้
frankhommers

@frankhommers ได้รับการกล่าวว่าตรวจสอบเฉพาะสำหรับบล็อก 16 บิต
5354

16 bits blocks สามารถเป็นอย่างอื่นได้มากกว่า 192.168
frankhommers

0

นอกจากนี้ยังมีรหัสง่ายๆสำหรับการรับ IP ของลูกค้า:

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

หวังว่ามันจะช่วยคุณ


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

ป้อนคำอธิบายรูปภาพที่นี่


5
คำตอบของคุณควรมีคำอธิบายว่ามันทำงานอย่างไรสำหรับกรณีของ OP และสำหรับผู้อ่านในอนาคต
Ronak Dhoot

มันจะดีกว่าที่จะรวมคำอธิบายของคำตอบสำหรับผู้อ่านในอนาคต
Nicolas Gervais

0

แก้ไขรหัสของ compman2408 เพื่อให้สามารถทำซ้ำ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;
}

และคุณสามารถเรียกมันว่า:

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

ด้านล่างการกระทำเดียวกัน

ฟังก์ชั่น LocalIP ()

โฮสต์ Dim เป็น String = Dns.GetHostEntry (Dns.GetHostName) .AddressList (1) .MapToIPv4.ToString

txtIP.Text = โฮสต์

กลับ True

ฟังก์ชั่นสิ้นสุด


ตัวอย่างด้านล่างคือการกระทำเดียวกัน Function LocalIP () Dim Host เป็น String = Dns.GetHostEntry (Dns.GetHostName) .AddressList (1) .MapToIPv4.ToString txtIP.Text = Host Return True End Function
YongJae Kim

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

รหัสหนึ่งบรรทัด: D


7
มันอาจส่ง OutOfRangeException ในบางกรณี
Loudenvier

5
นอกจากนี้คุณจะรู้ได้อย่างไรว่าคนที่คุณต้องการ? อะไรที่เหมาะกับคุณอาจจะผิดกับคนอื่น
ทำเครื่องหมาย

-3

หากคุณมีเครื่องเสมือนหรือการ์ดเครือข่ายพิเศษอาจมีค่าอื่น ๆ ในรายการที่อยู่ ข้อเสนอแนะของฉันคือการตรวจสอบรายการที่อยู่และพิมพ์ที่เหมาะสม ในรายการเคสของฉัน 3 คือที่อยู่ ipv4 ของเครื่องของฉัน

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

อย่าลืมเพิ่ม using System.Net;


1
แก้ไข; ทั้งหมดนี้เป็นที่อยู่ IP ของเครื่องของคุณ สิ่งที่คุณต้องการ แต่เป็นอีกเรื่องหนึ่ง โปรดทราบว่าคำสั่งซื้อสามารถเปลี่ยนแปลงได้และเนื่องจากวิธีการที่คุณใช้คุณจะต้องเดาเสมอ
ทำเครื่องหมาย

นั่นคือสิ่งที่ฉันพูดคุณควรตรวจสอบรายการที่อยู่และใช่มันคาดเดา แต่หลังจากที่ได้เห็นรายการทั้งหมดคาดเดาไม่ยากมาก
Bibaswann Bandyopadhyay

คุณจะรู้ได้อย่างไรว่าอะไรเหมาะสม การใช้โซลูชันของ compman2048 อย่างน้อยคุณจะรู้ว่าสิ่งใดเชื่อมโยงกับส่วนต่อประสาน
ทำเครื่องหมาย

วิธีแก้ปัญหานั้นไม่ได้ทำงานในคอมพิวเตอร์ของฉันเพราะฉันมี 2 อินเตอร์เฟส wlan, 2 เครื่องเสมือนและ 1 ตัวจำลองดังนั้นฉันจึงได้รับ IP จำนวนมาก แต่ถ้าคุณกำลังมองหาที่อยู่ภายในที่จัดไว้ให้โดยเราเตอร์มันจะเริ่มต้นด้วย 192 หรือ 172 หรือ 10 นั่นคือสิ่งที่ฉันเข้าใจ
Bibaswann Bandyopadhyay

เว้นแต่ว่าเราเตอร์ของคุณจะแจก IP สาธารณะซึ่งเป็นเรื่องแปลก แต่เป็นไปได้
ทำเครื่องหมาย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.