如何获得我的c#应用程序正在运行的服务器的IP地址?

我正在运行一个服务器,我想显示我自己的IP地址。

获取计算机自身(如果可能的话,外部)IP地址的语法是什么?

有人编写了以下代码。

IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily.ToString() == "InterNetwork")
{
localIP = ip.ToString();
}
}
return localIP;

然而,我通常不信任作者,我不理解这段代码。有更好的方法吗?

379338 次浏览

不,这几乎是最好的方法。作为一个机器可以有几个IP地址,你需要迭代他们的集合来找到合适的一个。

编辑:我唯一改变的是改变这个:

if (ip.AddressFamily.ToString() == "InterNetwork")

:

if (ip.AddressFamily == AddressFamily.InterNetwork)

不需要ToString一个枚举来进行比较。

namespace NKUtilities
{
using System;
using System.Net;
using System.Net.Sockets;


public class DNSUtility
{
public static int Main(string [] args)
{
string strHostName = "";
try {


if(args.Length == 0)
{
// 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);
}
else
{
// Otherwise, get the IP address of the host provided on the command line.
strHostName = args[0];
}


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


}
catch(SocketException se)
{
Console.WriteLine("{0} ({1})", se.Message, strHostName);
return -1;
}
catch(Exception ex)
{
Console.WriteLine("Error: {0}.", ex.Message);
return -1;
}
}
}
}

详见在这里

你必须记住你的电脑可以有多个IP(实际上它总是这样)-所以你是哪一个。

using System.Net;


string host = Dns.GetHostName();
IPHostEntry ip = Dns.GetHostEntry(host);
Console.WriteLine(ip.AddressList[0].ToString());

刚在我的机器上测试过了,还能用。

也许通过外部 IP你可以考虑(如果你在Web服务器上下文中)使用这个

Request.ServerVariables["LOCAL_ADDR"];

我问了你同样的问题,我在 stackoverflow文章中找到了它。

这对我很管用。

了解你的公共IP的唯一方法是让别人告诉你;这段代码可以帮助你:

public string GetPublicIP()
{
String direction = "";
WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
using (WebResponse response = request.GetResponse())
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
direction = stream.ReadToEnd();
}


//Search for the ip in the html
int first = direction.IndexOf("Address: ") + 9;
int last = direction.LastIndexOf("</body>");
direction = direction.Substring(first, last - first);


return direction;
}
WebClient webClient = new WebClient();
string IP = webClient.DownloadString("http://myip.ozymo.com/");

试试这个:

 IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
String MyIp = localIPs[0].ToString();

清洁和一体解决方案:D

//This returns the first IP4 address or null
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

为了获取当前的公网IP地址,你所需要做的就是在页面加载事件中创建一个ASPX页面,代码如下:

Response.Write(HttpContext.Current.Request.UserHostAddress.ToString());

如果你不能依赖于从DNS服务器获取你的IP地址(这发生在我身上),你可以使用以下方法:

System.Net.NetworkInformation命名空间包含一个NetworkInterface类,它有一个静态的GetAllNetworkInterfaces方法

此方法将返回您机器上的所有“网络接口”,而且通常有相当多的“网络接口”,即使您的机器上只安装了无线适配器和/或以太网适配器硬件。所有这些网络接口都有本地计算机的有效IP地址,尽管您可能只需要一个。

如果您正在寻找一个IP地址,那么您将需要筛选列表,直到您可以识别正确的地址。你可能需要做一些实验,但我成功地采用了以下方法:

  • 通过检查OperationalStatus == OperationalStatus.Up过滤掉任何非活动的网络接口。这将排除您的物理以太网适配器,例如,如果您没有插入网线。

对于每个NetworkInterface,你可以使用GetIPProperties方法来获得一个IPInterfaceProperties对象,而从IPInterfaceProperties对象中,你可以访问UnicastAddresses财产来获得一个UnicastIPAddressInformation对象列表。

  • 通过检查DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred过滤非首选单播地址
  • 通过检查AddressPreferredLifetime != UInt32.MaxValue过滤掉“虚拟”地址。

此时,我取与所有这些过滤器匹配的第一个单播地址(如果有的话)的地址。

编辑:

[2018年5月16日修订的代码,以包括上述文本中提到的重复地址检测状态和首选生存期的条件]

下面的示例演示了基于操作状态、地址族、排除环回地址(127.0.0.1)、重复地址检测状态和首选生存期的过滤。

static IEnumerable<IPAddress> GetLocalIpAddresses()
{
// Get the list of network interfaces for the local computer.
var adapters = NetworkInterface.GetAllNetworkInterfaces();


// Return the list of local IPv4 addresses excluding the local
// host, disconnected, and virtual addresses.
return (from adapter in adapters
let properties = adapter.GetIPProperties()
from address in properties.UnicastAddresses
where adapter.OperationalStatus == OperationalStatus.Up &&
address.Address.AddressFamily == AddressFamily.InterNetwork &&
!address.Equals(IPAddress.Loopback) &&
address.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred &&
address.AddressPreferredLifetime != UInt32.MaxValue
select address.Address);
}

这是在VB中获取所有本地ip的csv格式。网

Imports System.Net
Imports System.Net.Sockets


Function GetIPAddress() As String
Dim ipList As List(Of String) = New List(Of String)
Dim host As IPHostEntry
Dim localIP As String = "?"
host = Dns.GetHostEntry(Dns.GetHostName())
For Each ip As IPAddress In host.AddressList
If ip.AddressFamily = AddressFamily.InterNetwork Then
localIP = ip.ToString()
ipList.Add(localIP)
End If
Next
Dim ret As String = String.Join(",", ipList.ToArray)
Return ret
End Function
namespace NKUtilities
{
using System;
using System.Net;


public class DNSUtility
{
public static int Main (string [] args)
{


String strHostName = new String ("");
if (args.Length == 0)
{
// 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);
}
else
{
strHostName = args[0];
}


// Then using host name, get the IP address list..
IPHostEntry ipEntry = DNS.GetHostByName (strHostName);
IPAddress [] addr = ipEntry.AddressList;


for (int i = 0; i < addr.Length; i++)
{
Console.WriteLine ("IP Address {0}: {1} ", i, addr[i].ToString ());
}
return 0;
}
}
}
不要一直依赖互联网,因为你可以有多个设备也使用IP4,这会搞砸获取你的IP的结果。 现在,如果你愿意,你可以复制这篇文章,并请检查或更新为你认为合适的方式 首先我得到路由器(网关)的地址 如果它回来,我连接到网关(这意味着没有直接连接到调制解调器无线与否),那么我们有我们的网关地址作为IPAddress,否则我们一个空指针IPAddress引用 然后我们需要获取计算机的ip地址列表。这并不难,因为路由器(所有路由器)使用4个字节(…)。前三个字节是最重要的,因为任何连接到它的计算机都有与前三个字节匹配的IP4地址。例如:192.168.0.1是标准的路由器默认IP,除非管理员更改它。'192.168.0'或者其他我们需要匹配的东西。这就是我在IsAddressOfGateway函数中所做的。 长度匹配的原因是因为不是所有地址(仅用于计算机)的长度都是4字节。如果你在cmd中输入netstat,你会发现这是真的。结果出来了。是的,要真正得到你想要的东西还需要多花点功夫。排除法。 看在上帝的份上,不要通过ping来找到地址,这需要时间,因为首先你要发送被ping的地址,然后它必须将结果发回。不,直接使用。net类处理您的系统环境,当它只与您的计算机有关时,您将得到您正在寻找的答案

现在如果你直接连接到你的调制解调器,这个过程几乎是一样的,因为调制解调器是你的网关,但子掩码是不一样的,因为你通过调制解调器直接从你的DNS服务器获取信息,而不是被为你提供互联网的路由器屏蔽,尽管你仍然可以使用相同的代码,因为分配给调制解调器的IP的最后一个字节是1。因此,如果从调制解调器发送的IP更改为111.111.111.1',那么您将得到111.111.111。(一些字节值)。请记住,我们需要找到网关信息,因为有更多的设备处理互联网连接比你的路由器和调制解调器。

现在你知道为什么不改变路由器的前两个字节192和168了。这些是严格区分路由器,而不是互联网使用,否则我们将有一个严重的问题与IP协议和双ping导致您的计算机崩溃。假设您分配的路由器IP是192.168.44.103,然后单击一个具有该IP的站点。OMG !你的计算机将不知道要ping什么。就在这里坠毁。为了避免这个问题,只有路由器被分配这些,而不是用于互联网使用。因此,保留路由器的前两个字节。

static IPAddress FindLanAddress()
{
IPAddress gateway = FindGetGatewayAddress();
if (gateway == null)
return null;


IPAddress[] pIPAddress = Dns.GetHostAddresses(Dns.GetHostName());


foreach (IPAddress address in pIPAddress)            {
if (IsAddressOfGateway(address, gateway))
return address;
return null;
}
static bool IsAddressOfGateway(IPAddress address, IPAddress gateway)
{
if (address != null && gateway != null)
return IsAddressOfGateway(address.GetAddressBytes(),gateway.GetAddressBytes());
return false;
}
static bool IsAddressOfGateway(byte[] address, byte[] gateway)
{
if (address != null && gateway != null)
{
int gwLen = gateway.Length;
if (gwLen > 0)
{
if (address.Length == gateway.Length)
{
--gwLen;
int counter = 0;
for (int i = 0; i < gwLen; i++)
{
if (address[i] == gateway[i])
++counter;
}
return (counter == gwLen);
}
}
}
return false;


}
static IPAddress FindGetGatewayAddress()
{
IPGlobalProperties ipGlobProps = IPGlobalProperties.GetIPGlobalProperties();


foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
IPInterfaceProperties ipInfProps = ni.GetIPProperties();
foreach (GatewayIPAddressInformation gi in ipInfProps.GatewayAddresses)
return gi.Address;
}
return null;
}
using System;
using System.Net;


namespace IPADDRESS
{
class Program
{
static void Main(string[] args)
{
String strHostName = string.Empty;
if (args.Length == 0)
{
/* First get the host name of local machine.*/
strHostName = Dns.GetHostName();
Console.WriteLine("Local Machine's Host Name: " + strHostName);
}
else
{
strHostName = args[0];
}
/* Then using host name, get the IP address list..*/
IPHostEntry ipEntry = Dns.GetHostByName(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();
}
}
}
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

简单的一行代码,返回第一个内部IPV4地址,如果没有则返回null。作为上面的注释添加,但可能对某人有用(上面的一些解决方案将返回多个需要进一步过滤的地址)。

它也很容易返回环回而不是null,我猜用:

return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork) ?? new IPAddress( new byte[] {127, 0, 0, 1} );

为了找到IP地址列表,我已经使用了这个解决方案

public static IEnumerable<string> GetAddresses()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
return (from ip in host.AddressList where ip.AddressFamily == AddressFamily.lo select ip.ToString()).ToList();
}

但我个人喜欢下面的解决方案,以获得本地有效的 IP地址

public static IPAddress GetIPAddress(string hostName)
{
Ping ping = new Ping();
var replay = ping.Send(hostName);


if (replay.Status == IPStatus.Success)
{
return replay.Address;
}
return null;
}


public static void Main()
{
Console.WriteLine("Local IP Address: " + GetIPAddress(Dns.GetHostName()));
Console.WriteLine("Google IP:" + GetIPAddress("google.com");
Console.ReadLine();
}

LINQ解决方案:

Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).Select(ip => ip.ToString()).FirstOrDefault() ?? ""

我只是想添加我自己的一行代码(尽管已经有许多其他有用的答案)。


string ipAddress = new WebClient().DownloadString("http://icanhazip.com");

如果你想避免使用DNS:

List<IPAddress> ipList = new List<IPAddress>();
foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
foreach (var address in netInterface.GetIPProperties().UnicastAddresses)
{
if (address.Address.AddressFamily == AddressFamily.InterNetwork)
{
Console.WriteLine("found IP " + address.Address.ToString());
ipList.Add(address.Address);
}
}
}

这是我解决它的方法。我知道如果你有几个物理接口,这可能不会选择你想要的确切的eth。

private string FetchIP()
{
//Get all IP registered
List<string> IPList = new List<string>();
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
IPList.Add(ip.ToString());
}
}


//Find the first IP which is not only local
foreach (string a in IPList)
{
Ping p = new Ping();
string[] b = a.Split('.');
string ip2 = b[0] + "." + b[1] + "." + b[2] + ".1";
PingReply t = p.Send(ip2);
p.Dispose();
if (t.Status == IPStatus.Success && ip2 != a)
{
return a;
}
}
return null;
}
如果你在内部网络中运行,你将能够获得本地机器的IP地址,如果不是,你将获得外部IP地址: 网络:< / p >
//this will bring the IP for the current machine on browser
System.Web.HttpContext.Current.Request.UserHostAddress

桌面:

//This one will bring all local IPs for the desired namespace
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());

这个问题没有说ASP。NET MVC,但我还是把这个留在这里:

Request.UserHostAddress

以最快的方式获得远程 IP 地址。您必须使用下载程序,或者在计算机上创建服务器。

使用这个简单代码的缺点是: (推荐使用)需要3-5秒才能获得远程 IP 地址,因为初始化时 WebClient 总是需要3-5秒来检查代理设置。

 public static string GetIP()
{
string externalIP = "";
externalIP = new WebClient().DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}

我是这么修的。.(第一次仍然需要3-5秒) ,但在此之后,它将总是得到您的远程 IP 地址在0-2秒取决于您的连接。

public static WebClient webclient = new WebClient();
public static string GetIP()
{
string externalIP = "";
externalIP = webclient.DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}

使用 LINQ 以字符串的形式获取所有 IP 地址:

using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
...
string[] allIpAddresses = NetworkInterface.GetAllNetworkInterfaces()
.SelectMany(c=>c.GetIPProperties().UnicastAddresses
.Where(d=>d.Address.AddressFamily == AddressFamily.InterNetwork)
.Select(d=>d.Address.ToString())
).ToArray();

过滤掉私人信件。

首先,定义一个扩展方法 IsPrivate():

public static class IPAddressExtensions
{
// Collection of private CIDRs (IpAddress/Mask)
private static Tuple<int, int>[] _privateCidrs = new []{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}
.Select(c=>Tuple.Create(BitConverter.ToInt32(IPAddress
.Parse(c.Split('/')[0]).GetAddressBytes(), 0)
, IPAddress.HostToNetworkOrder(-1 << (32-int.Parse(c.Split('/')[1])))))
.ToArray();
public static bool IsPrivate(this IPAddress ipAddress)
{
int ip = BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0);
return _privateCidrs.Any(cidr=>(ip & cidr.Item2)==(cidr.Item1 & cidr.Item2));
}
}

然后用它过滤掉私人 IP 地址:

string[] publicIpAddresses = NetworkInterface.GetAllNetworkInterfaces()
.SelectMany(c=>c.GetIPProperties().UnicastAddresses
.Where(d=>d.Address.AddressFamily == AddressFamily.InterNetwork
&& !d.Address.IsPrivate() // Filter out private ones
)
.Select(d=>d.Address.ToString())
).ToArray();

它对我很有用... ... 而且在大多数情况下(如果不是全部的话)应该比查询 DNS 服务器快。感谢威利博士的学徒(给你)。

// ************************************************************************
/// <summary>
/// Will search for the an active NetworkInterafce that has a Gateway, otherwise
/// it will fallback to try from the DNS which is not safe.
/// </summary>
/// <returns></returns>
public static NetworkInterface GetMainNetworkInterface()
{
List<NetworkInterface> candidates = new List<NetworkInterface>();


if (NetworkInterface.GetIsNetworkAvailable())
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (
NetworkInterface ni in NetworkInterfaces)
{
if (ni.OperationalStatus == OperationalStatus.Up)
candidates.Add(ni);
}
}


if (candidates.Count == 1)
{
return candidates[0];
}


// Accoring to our tech, the main NetworkInterface should have a Gateway
// and it should be the ony one with a gateway.
if (candidates.Count > 1)
{
for (int n = candidates.Count - 1; n >= 0; n--)
{
if (candidates[n].GetIPProperties().GatewayAddresses.Count == 0)
{
candidates.RemoveAt(n);
}
}


if (candidates.Count == 1)
{
return candidates[0];
}
}


// Fallback to try by getting my ipAdress from the dns
IPAddress myMainIpAdress = null;
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork) // Get the first IpV4
{
myMainIpAdress = ip;
break;
}
}


if (myMainIpAdress != null)
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (NetworkInterface ni in NetworkInterfaces)
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
IPInterfaceProperties props = ni.GetIPProperties();
foreach (UnicastIPAddressInformation ai in props.UnicastAddresses)
{
if (ai.Address.Equals(myMainIpAdress))
{
return ni;
}
}
}
}
}


return null;
}


// ******************************************************************
/// <summary>
/// AddressFamily.InterNetwork = IPv4
/// Thanks to Dr. Wilys Apprentice at
/// http://stackoverflow.com/questions/1069103/how-to-get-the-ip-address-of-the-server-on-which-my-c-sharp-application-is-runni
/// using System.Net.NetworkInformation;
/// </summary>
/// <param name="mac"></param>
/// <param name="addressFamily">AddressFamily.InterNetwork = IPv4,  AddressFamily.InterNetworkV6 = IPv6</param>
/// <returns></returns>
public static IPAddress GetIpFromMac(PhysicalAddress mac, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (NetworkInterface ni in NetworkInterfaces)
{
if (ni.GetPhysicalAddress().Equals(mac))
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
IPInterfaceProperties props = ni.GetIPProperties();
foreach (UnicastIPAddressInformation ai in props.UnicastAddresses)
{
if (ai.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred)
{
if (ai.Address.AddressFamily == addressFamily)
{
return ai.Address;
}
}
}
}
}
}


return null;
}


// ******************************************************************
/// <summary>
/// Return the best guess of main ipAdress. To get it in the form aaa.bbb.ccc.ddd just call
/// '?.ToString() ?? ""' on the result.
/// </summary>
/// <returns></returns>
public static IPAddress GetMyInternetIpAddress()
{
NetworkInterface ni = GetMainNetworkInterface();
IPAddress ipAddress = GetIpFromMac(ni.GetPhysicalAddress());
if (ipAddress == null) // could it be possible ?
{
ipAddress = GetIpFromMac(ni.GetPhysicalAddress(), AddressFamily.InterNetworkV6);
}


return ipAddress;
}


// ******************************************************************

作为参考,这是我定义它的完整类代码:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading.Tasks;


namespace TcpMonitor
{
/*
Usage:
var cons = TcpHelper.GetAllTCPConnections();
foreach (TcpHelper.MIB_TCPROW_OWNER_PID c in cons) ...
*/


public class NetHelper
{
[DllImport("iphlpapi.dll", SetLastError = true)]
static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref int dwOutBufLen, bool sort, int ipVersion, UDP_TABLE_CLASS tblClass, uint reserved = 0);


public enum UDP_TABLE_CLASS
{
UDP_TABLE_BASIC,
UDP_TABLE_OWNER_PID,
UDP_TABLE_OWNER_MODULE
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_UDPTABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_UDPROW_OWNER_PID[] table;
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_UDPROW_OWNER_PID
{
public uint localAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] localPort;
public uint owningPid;


public uint ProcessId
{
get { return owningPid; }
}


public IPAddress LocalAddress
{
get { return new IPAddress(localAddr); }
}


public ushort LocalPort
{
get { return BitConverter.ToUInt16(localPort.Take(2).Reverse().ToArray(), 0); }
}
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_UDP6TABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_UDP6ROW_OWNER_PID[] table;
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_UDP6ROW_OWNER_PID
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] localAddr;
public uint localScopeId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] localPort;
public uint owningPid;
public uint ProcessId
{
get { return owningPid; }
}


public IPAddress LocalAddress
{
get { return new IPAddress(localAddr, localScopeId); }
}


public ushort LocalPort
{
get { return BitConverter.ToUInt16(localPort.Take(2).Reverse().ToArray(), 0); }
}
}


public static List<MIB_UDPROW_OWNER_PID> GetAllUDPConnections()
{
return GetUDPConnections<MIB_UDPROW_OWNER_PID, MIB_UDPTABLE_OWNER_PID> (AF_INET);
}


public static List<MIB_UDP6ROW_OWNER_PID> GetAllUDPv6Connections()
{
return GetUDPConnections<MIB_UDP6ROW_OWNER_PID, MIB_UDP6TABLE_OWNER_PID>(AF_INET6);
}


private static List<IPR> GetUDPConnections<IPR, IPT>(int ipVersion)//IPR = Row Type, IPT = Table Type
{
List<IPR> result = null;


IPR[] tableRows = null;
int buffSize = 0;


var dwNumEntriesField = typeof(IPT).GetField("dwNumEntries");


// how much memory do we need?
uint ret = GetExtendedUdpTable(IntPtr.Zero, ref buffSize, true, ipVersion, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
IntPtr udpTablePtr = Marshal.AllocHGlobal(buffSize);


try
{
ret = GetExtendedUdpTable(udpTablePtr, ref buffSize, true, ipVersion, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
if (ret != 0)
return new List<IPR>();


// get the number of entries in the table
IPT table = (IPT)Marshal.PtrToStructure(udpTablePtr, typeof(IPT));
int rowStructSize = Marshal.SizeOf(typeof(IPR));
uint numEntries = (uint)dwNumEntriesField.GetValue(table);


// buffer we will be returning
tableRows = new IPR[numEntries];


IntPtr rowPtr = (IntPtr)((long)udpTablePtr + 4);
for (int i = 0; i < numEntries; i++)
{
IPR tcpRow = (IPR)Marshal.PtrToStructure(rowPtr, typeof(IPR));
tableRows[i] = tcpRow;
rowPtr = (IntPtr)((long)rowPtr + rowStructSize);   // next entry
}
}
finally
{
result = tableRows?.ToList() ?? new List<IPR>();


// Free the Memory
Marshal.FreeHGlobal(udpTablePtr);
}


return result;
}


[DllImport("iphlpapi.dll", SetLastError = true)]
static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_CLASS tblClass, uint reserved = 0);






public enum MIB_TCP_STATE
{
MIB_TCP_STATE_CLOSED = 1,
MIB_TCP_STATE_LISTEN = 2,
MIB_TCP_STATE_SYN_SENT = 3,
MIB_TCP_STATE_SYN_RCVD = 4,
MIB_TCP_STATE_ESTAB = 5,
MIB_TCP_STATE_FIN_WAIT1 = 6,
MIB_TCP_STATE_FIN_WAIT2 = 7,
MIB_TCP_STATE_CLOSE_WAIT = 8,
MIB_TCP_STATE_CLOSING = 9,
MIB_TCP_STATE_LAST_ACK = 10,
MIB_TCP_STATE_TIME_WAIT = 11,
MIB_TCP_STATE_DELETE_TCB = 12
}


public enum TCP_TABLE_CLASS
{
TCP_TABLE_BASIC_LISTENER,
TCP_TABLE_BASIC_CONNECTIONS,
TCP_TABLE_BASIC_ALL,
TCP_TABLE_OWNER_PID_LISTENER,
TCP_TABLE_OWNER_PID_CONNECTIONS,
TCP_TABLE_OWNER_PID_ALL,
TCP_TABLE_OWNER_MODULE_LISTENER,
TCP_TABLE_OWNER_MODULE_CONNECTIONS,
TCP_TABLE_OWNER_MODULE_ALL
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_TCPROW_OWNER_PID[] table;
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCP6TABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_TCP6ROW_OWNER_PID[] table;
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID
{
public uint state;
public uint localAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] localPort;
public uint remoteAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] remotePort;
public uint owningPid;


public uint ProcessId
{
get { return owningPid; }
}


public IPAddress LocalAddress
{
get { return new IPAddress(localAddr); }
}


public ushort LocalPort
{
get
{
return BitConverter.ToUInt16(new byte[2] { localPort[1], localPort[0] }, 0);
}
}


public IPAddress RemoteAddress
{
get { return new IPAddress(remoteAddr); }
}


public ushort RemotePort
{
get
{
return BitConverter.ToUInt16(new byte[2] { remotePort[1], remotePort[0] }, 0);
}
}


public MIB_TCP_STATE State
{
get { return (MIB_TCP_STATE)state; }
}
}




[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCP6ROW_OWNER_PID
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] localAddr;
public uint localScopeId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] localPort;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] remoteAddr;
public uint remoteScopeId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] remotePort;
public uint state;
public uint owningPid;


public uint ProcessId
{
get { return owningPid; }
}


public long LocalScopeId
{
get { return localScopeId; }
}


public IPAddress LocalAddress
{
get { return new IPAddress(localAddr, LocalScopeId); }
}


public ushort LocalPort
{
get { return BitConverter.ToUInt16(localPort.Take(2).Reverse().ToArray(), 0); }
}


public long RemoteScopeId
{
get { return remoteScopeId; }
}


public IPAddress RemoteAddress
{
get { return new IPAddress(remoteAddr, RemoteScopeId); }
}


public ushort RemotePort
{
get { return BitConverter.ToUInt16(remotePort.Take(2).Reverse().ToArray(), 0); }
}


public MIB_TCP_STATE State
{
get { return (MIB_TCP_STATE)state; }
}
}




public const int AF_INET = 2;    // IP_v4 = System.Net.Sockets.AddressFamily.InterNetwork
public const int AF_INET6 = 23;  // IP_v6 = System.Net.Sockets.AddressFamily.InterNetworkV6


public static Task<List<MIB_TCPROW_OWNER_PID>> GetAllTCPConnectionsAsync()
{
return Task.Run(() => GetTCPConnections<MIB_TCPROW_OWNER_PID, MIB_TCPTABLE_OWNER_PID>(AF_INET));
}


public static List<MIB_TCPROW_OWNER_PID> GetAllTCPConnections()
{
return GetTCPConnections<MIB_TCPROW_OWNER_PID, MIB_TCPTABLE_OWNER_PID>(AF_INET);
}


public static Task<List<MIB_TCP6ROW_OWNER_PID>> GetAllTCPv6ConnectionsAsync()
{
return Task.Run(()=>GetTCPConnections<MIB_TCP6ROW_OWNER_PID, MIB_TCP6TABLE_OWNER_PID>(AF_INET6));
}


public static List<MIB_TCP6ROW_OWNER_PID> GetAllTCPv6Connections()
{
return GetTCPConnections<MIB_TCP6ROW_OWNER_PID, MIB_TCP6TABLE_OWNER_PID>(AF_INET6);
}


private static List<IPR> GetTCPConnections<IPR, IPT>(int ipVersion)//IPR = Row Type, IPT = Table Type
{
List<IPR> result = null;


IPR[] tableRows = null;
int buffSize = 0;


var dwNumEntriesField = typeof(IPT).GetField("dwNumEntries");


// how much memory do we need?
uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, ipVersion, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
IntPtr tcpTablePtr = Marshal.AllocHGlobal(buffSize);


try
{
ret = GetExtendedTcpTable(tcpTablePtr, ref buffSize, true, ipVersion, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
if (ret != 0)
return new List<IPR>();


// get the number of entries in the table
IPT table = (IPT)Marshal.PtrToStructure(tcpTablePtr, typeof(IPT));
int rowStructSize = Marshal.SizeOf(typeof(IPR));
uint numEntries = (uint)dwNumEntriesField.GetValue(table);


// buffer we will be returning
tableRows = new IPR[numEntries];


IntPtr rowPtr = (IntPtr)((long)tcpTablePtr + 4);
for (int i = 0; i < numEntries; i++)
{
IPR tcpRow = (IPR)Marshal.PtrToStructure(rowPtr, typeof(IPR));
tableRows[i] = tcpRow;
rowPtr = (IntPtr)((long)rowPtr + rowStructSize);   // next entry
}
}
finally
{
result = tableRows?.ToList() ?? new List<IPR>();


// Free the Memory
Marshal.FreeHGlobal(tcpTablePtr);
}


return result;
}


public static string GetTcpStateName(MIB_TCP_STATE state)
{
switch (state)
{
case MIB_TCP_STATE.MIB_TCP_STATE_CLOSED:
return "Closed";
case MIB_TCP_STATE.MIB_TCP_STATE_LISTEN:
return "Listen";
case MIB_TCP_STATE.MIB_TCP_STATE_SYN_SENT:
return "SynSent";
case MIB_TCP_STATE.MIB_TCP_STATE_SYN_RCVD:
return "SynReceived";
case MIB_TCP_STATE.MIB_TCP_STATE_ESTAB:
return "Established";
case MIB_TCP_STATE.MIB_TCP_STATE_FIN_WAIT1:
return "FinWait 1";
case MIB_TCP_STATE.MIB_TCP_STATE_FIN_WAIT2:
return "FinWait 2";
case MIB_TCP_STATE.MIB_TCP_STATE_CLOSE_WAIT:
return "CloseWait";
case MIB_TCP_STATE.MIB_TCP_STATE_CLOSING:
return "Closing";
case MIB_TCP_STATE.MIB_TCP_STATE_LAST_ACK:
return "LastAck";
case MIB_TCP_STATE.MIB_TCP_STATE_TIME_WAIT:
return "TimeWait";
case MIB_TCP_STATE.MIB_TCP_STATE_DELETE_TCB:
return "DeleteTCB";
default:
return ((int)state).ToString();
}
}


private static readonly ConcurrentDictionary<string, string> DicOfIpToHostName = new ConcurrentDictionary<string, string>();


public const string UnknownHostName = "Unknown";


// ******************************************************************
public static string GetHostName(IPAddress ipAddress)
{
return GetHostName(ipAddress.ToString());
}


// ******************************************************************
public static string GetHostName(string ipAddress)
{
string hostName = null;


if (!DicOfIpToHostName.TryGetValue(ipAddress, out hostName))
{
try
{
if (ipAddress == "0.0.0.0" || ipAddress == "::")
{
hostName = ipAddress;
}
else
{
hostName = Dns.GetHostEntry(ipAddress).HostName;
}
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
hostName = UnknownHostName;
}


DicOfIpToHostName[ipAddress] = hostName;
}


return hostName;
}


// ************************************************************************
/// <summary>
/// Will search for the an active NetworkInterafce that has a Gateway, otherwise
/// it will fallback to try from the DNS which is not safe.
/// </summary>
/// <returns></returns>
public static NetworkInterface GetMainNetworkInterface()
{
List<NetworkInterface> candidates = new List<NetworkInterface>();


if (NetworkInterface.GetIsNetworkAvailable())
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (
NetworkInterface ni in NetworkInterfaces)
{
if (ni.OperationalStatus == OperationalStatus.Up)
candidates.Add(ni);
}
}


if (candidates.Count == 1)
{
return candidates[0];
}


// Accoring to our tech, the main NetworkInterface should have a Gateway
// and it should be the ony one with a gateway.
if (candidates.Count > 1)
{
for (int n = candidates.Count - 1; n >= 0; n--)
{
if (candidates[n].GetIPProperties().GatewayAddresses.Count == 0)
{
candidates.RemoveAt(n);
}
}


if (candidates.Count == 1)
{
return candidates[0];
}
}


// Fallback to try by getting my ipAdress from the dns
IPAddress myMainIpAdress = null;
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork) // Get the first IpV4
{
myMainIpAdress = ip;
break;
}
}


if (myMainIpAdress != null)
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (NetworkInterface ni in NetworkInterfaces)
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
IPInterfaceProperties props = ni.GetIPProperties();
foreach (UnicastIPAddressInformation ai in props.UnicastAddresses)
{
if (ai.Address.Equals(myMainIpAdress))
{
return ni;
}
}
}
}
}


return null;
}


// ******************************************************************
/// <summary>
/// AddressFamily.InterNetwork = IPv4
/// Thanks to Dr. Wilys Apprentice at
/// http://stackoverflow.com/questions/1069103/how-to-get-the-ip-address-of-the-server-on-which-my-c-sharp-application-is-runni
/// using System.Net.NetworkInformation;
/// </summary>
/// <param name="mac"></param>
/// <param name="addressFamily">AddressFamily.InterNetwork = IPv4,  AddressFamily.InterNetworkV6 = IPv6</param>
/// <returns></returns>
public static IPAddress GetIpFromMac(PhysicalAddress mac, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
NetworkInterface[] NetworkInterfaces =
NetworkInterface.GetAllNetworkInterfaces();


foreach (NetworkInterface ni in NetworkInterfaces)
{
if (ni.GetPhysicalAddress().Equals(mac))
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
IPInterfaceProperties props = ni.GetIPProperties();
foreach (UnicastIPAddressInformation ai in props.UnicastAddresses)
{
if (ai.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred)
{
if (ai.Address.AddressFamily == addressFamily)
{
return ai.Address;
}
}
}
}
}
}


return null;
}


// ******************************************************************
/// <summary>
/// Return the best guess of main ipAdress. To get it in the form aaa.bbb.ccc.ddd just call
/// '?.ToString() ?? ""' on the result.
/// </summary>
/// <returns></returns>
public static IPAddress GetMyInternetIpAddress()
{
NetworkInterface ni = GetMainNetworkInterface();
IPAddress ipAddress = GetIpFromMac(ni.GetPhysicalAddress());
if (ipAddress == null) // could it be possible ?
{
ipAddress = GetIpFromMac(ni.GetPhysicalAddress(), AddressFamily.InterNetworkV6);
}


return ipAddress;
}


// ******************************************************************
public static bool IsBroadcastAddress(IPAddress ipAddress)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
return ipAddress.GetAddressBytes()[3] == 255;
}


if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
return false; // NO broadcast in IPv6
}


return false;
}


// ******************************************************************
public static bool IsMulticastAddress(IPAddress ipAddress)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
// Source: https://technet.microsoft.com/en-us/library/cc772041(v=ws.10).aspx
return ipAddress.GetAddressBytes()[0] >= 224 && ipAddress.GetAddressBytes()[0] <= 239;
}


if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
return ipAddress.IsIPv6Multicast;
}


return false;
}


// ******************************************************************


}
}

另一种获取公共 IP 地址的方法是使用 OpenDNS 的 resolve1.opendns.com服务器和 myip.opendns.com作为请求。

在命令行上,这是:

  nslookup myip.opendns.com resolver1.opendns.com

或者在 C # 中使用 DNSClient 代码:

  var lookup = new LookupClient(new IPAddress(new byte[] { 208, 67, 222, 222 }));
var result = lookup.Query("myip.opendns.com", QueryType.ANY);

这比访问 http 端点和解析响应要干净一些。

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