C# 获取本机IP地址的方法文档
概述
本文档整理了在C#中获取本机IP地址的多种方法,涵盖了从简单到复杂的各种场景,包括获取单个IP地址、所有网络接口信息、IPv4/IPv6地址筛选等。
方法列表
方法一:使用 Dns.GetHostEntry()(简单通用)
using System;
using System.Net;
using System.Net.Sockets;
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!");
}
特点: - 简单易用 - 返回第一个找到的IPv4地址 - 可能返回127.0.0.1(回环地址)
方法二:使用 NetworkInterface(推荐 - 最精确)
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
public static string GetLocalIPAddress()
{
// 获取所有活动的网络接口
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
.Where(n => n.OperationalStatus == OperationalStatus.Up &&
n.NetworkInterfaceType != NetworkInterfaceType.Loopback);
foreach (var networkInterface in networkInterfaces)
{
// 获取IP配置信息
var ipProperties = networkInterface.GetIPProperties();
// 获取IPv4地址
var ipv4Address = ipProperties.UnicastAddresses
.FirstOrDefault(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork);
if (ipv4Address != null)
{
return ipv4Address.Address.ToString();
}
}
return "No IPv4 address found";
}
特点: - 精确控制网络接口 - 可筛选活动接口和排除回环接口 - 提供完整的网络接口信息
方法三:使用 Socket 连接外部地址
using System.Net;
using System.Net.Sockets;
public static string GetLocalIPAddress()
{
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530); // 连接Google的DNS服务器
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
return endPoint.Address.ToString();
}
}
特点: - 通过实际连接获取本地出口IP - 适用于NAT环境 - 需要外部网络连接
方法四:获取所有IP地址(完整信息)
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Collections.Generic;
public class NetworkInfo
{
public static List<string> GetAllIPAddresses()
{
List<string> ipAddresses = new List<string>();
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
ipAddresses.Add($"{ip.AddressFamily}: {ip}");
}
return ipAddresses;
}
public static void DisplayNetworkInfo()
{
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var ni in networkInterfaces)
{
Console.WriteLine($"接口名称: {ni.Name}");
Console.WriteLine($"描述: {ni.Description}");
Console.WriteLine($"状态: {ni.OperationalStatus}");
Console.WriteLine($"类型: {ni.NetworkInterfaceType}");
var ipProperties = ni.GetIPProperties();
foreach (var ip in ipProperties.UnicastAddresses)
{
Console.WriteLine($" IP地址: {ip.Address} ({ip.Address.AddressFamily})");
Console.WriteLine($" 子网掩码: {ip.IPv4Mask}");
}
Console.WriteLine("---");
}
}
}
方法五:异步版本
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
public static async Task<string> GetLocalIPAddressAsync()
{
var hostEntry = await Dns.GetHostEntryAsync(Dns.GetHostName());
foreach (var ip in hostEntry.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
return "No IPv4 address found";
}
实用工具类
using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
public static class NetworkHelper
{
// 获取本机IPv4地址(优先获取非内网地址)
public static string GetLocalIPv4()
{
try
{
var addresses = Dns.GetHostAddresses(Dns.GetHostName())
.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(ip) &&
!IsInternalIP(ip))
.Select(ip => ip.ToString())
.ToList();
return addresses.FirstOrDefault() ?? "127.0.0.1";
}
catch
{
return "127.0.0.1";
}
}
// 判断是否为内网IP
private static bool IsInternalIP(IPAddress ip)
{
byte[] bytes = ip.GetAddressBytes();
// 10.0.0.0/8
if (bytes[0] == 10) return true;
// 172.16.0.0/12
if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) return true;
// 192.168.0.0/16
if (bytes[0] == 192 && bytes[1] == 168) return true;
// 169.254.0.0/16 (APIPA)
if (bytes[0] == 169 && bytes[1] == 254) return true;
return false;
}
// 获取指定网络接口的IP
public static string GetIPByInterface(string interfaceName)
{
var networkInterface = NetworkInterface.GetAllNetworkInterfaces()
.FirstOrDefault(ni => ni.Name.Equals(interfaceName, StringComparison.OrdinalIgnoreCase));
if (networkInterface != null)
{
var ipProperties = networkInterface.GetIPProperties();
var ipv4Address = ipProperties.UnicastAddresses
.FirstOrDefault(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork);
return ipv4Address?.Address.ToString() ?? "Not found";
}
return "Interface not found";
}
}
使用示例
class Program
{
static void Main()
{
// 获取本机IPv4地址
Console.WriteLine($"本机IPv4地址: {NetworkHelper.GetLocalIPv4()}");
// 获取所有网络接口信息
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var ni in interfaces)
{
if (ni.OperationalStatus == OperationalStatus.Up)
{
Console.WriteLine($"{ni.Name}: {NetworkHelper.GetIPByInterface(ni.Name)}");
}
}
}
}
注意事项
1. 网络接口状态
- 建议只获取状态为
OperationalStatus.Up的接口 - 排除回环接口 (
NetworkInterfaceType.Loopback)
2. IP地址类型
- IPv4:
AddressFamily.InterNetwork - IPv6:
AddressFamily.InterNetworkV6 - 根据实际需求选择合适的地址类型
3. 异常处理
网络操作可能因以下原因失败: - 无网络连接 - 权限不足 - DNS解析失败
建议添加适当的异常处理机制。
4. 多网卡环境
机器可能有多个网络接口卡(NIC),每个NIC可能有多个IP地址: - 有线网卡 - 无线网卡 - 虚拟网卡(VMware、VirtualBox等) - VPN虚拟网卡
5. 内网IP地址范围
常见内网IP地址段:
- 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
- 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
- 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
- 169.254.0.0/16 (APIPA,自动私有IP寻址)
6. 特殊地址
127.0.0.1:本地回环地址0.0.0.0:任意地址255.255.255.255:广播地址
性能考虑
- 缓存结果:频繁获取IP地址时可考虑缓存
- 异步操作:避免阻塞UI线程,使用异步方法
- 最小权限:应用程序应以最小必要权限运行
推荐方案
| 场景 | 推荐方法 | 理由 |
|---|---|---|
| 快速获取IP | 方法一(Dns.GetHostEntry) | 简单快速,适用于大多数场景 |
| 精确控制 | 方法二(NetworkInterface) | 可筛选接口,信息完整 |
| 获取出口IP | 方法三(Socket连接) | 适用于NAT环境 |
| 完整网络信息 | 方法四(NetworkInterface) | 获取所有接口详细信息 |
| 异步应用 | 方法五(异步版本) | 避免阻塞,提高响应性 |
总结
在C#中获取本机IP地址有多种方法,选择哪种方法取决于具体需求:
- 简单场景:使用方法一
- 精确控制:使用方法二(推荐)
- 特殊需求:根据实际情况选择其他方法
建议在生产环境中使用方法二,因为它提供了最准确和完整的网络接口信息,能够处理复杂的网络环境。
文档版本:1.0
最后更新:2023年10月
适用框架:.NET Framework 4.5+ / .NET Core 2.0+ / .NET 5+