C#验证IP是否为局域网地址的三种方法

前一阵子有【广州.NET群】的客户问起这个问题,说他们需要验证客户输入的网站是否为局域网。其实局域网的IP并没有确定的定义,只要是局域网中,即可设置为任何一个IP

但确实存在一个内网保留地址的定义,它会确保公网IPv4的地址不会分配在“内网保留地址”中,该地址定义如下:

  1. 10.0.0.0/8,即10.0.0.0-10.255.255.255;
  2. 172.16.0.0/12,即172.16.0.0-172.31.255.255;
  3. 192.168.0.0/16,即192.168.0.0-192.168.255.255

客户澄清,他确实就是想验证IPv4字符串是否为内网保留地址

下面我们来想想几种验证IPv4地址字符串是否为内网保留地址的方法。

首先写出该方法的签名:

bool IsPrivateNetwork(string ipv4Address)
{
}

然后构建测试数据,显示期待结果:

var testData = new Dictionary<string, bool>
{
[""] = false,
["Not A IP"] = false,
["225.5.5.5"] = false,
["175.10.74.64"] = false,
["192.168.1.13"] = true,
["10.10.24.220"] = true,
["172.24.1.120"] = true,
["172.32.1.120"] = false,
}; string output = String.Join("\r\n",
testData.Select(x => $"[{x.Key,12}] Expected: {x.Value,5},\tActual: {IsPrivateNetwork(x.Key),5}")); Console.WriteLine(output);

方法1——StartsWith()

这是最容易想到的方法,用字符串的SubstringStartsWith等方式来实现:

bool IsPrivateNetwork(string ipv4Address)
{
if (IPAddress.TryParse(ipv4Address, out _))
{
if (ipv4Address.StartsWith("192.168.") || ipv4Address.StartsWith("10."))
{
return true;
} if (ipv4Address.StartsWith("172."))
{
string seg2 = ipv4Address[4..7];
if (seg2.EndsWith('.') &&
String.Compare(seg2, "16.") >= 0 &&
String.Compare(seg2, "31.") <= 0)
{
return true;
}
}
} return false;
}

注意这种方式在验证A类网站和C类网站时都非常简单(确实约大多数客户都会用这两种)。B类网络是个特例,让这个代码稍复杂化了,需要多对几个字符串进行判断——导致代码比较复杂。

输入结果如下:


[ ] Expected: False, Actual: False
[ Not A IP] Expected: False, Actual: False
[ 225.5.5.5] Expected: False, Actual: False
[175.10.74.64] Expected: False, Actual: False
[192.168.1.13] Expected: True, Actual: True
[10.10.24.220] Expected: True, Actual: True
[172.24.1.120] Expected: True, Actual: True
[172.32.1.120] Expected: False, Actual: False

我觉得这种方法……还挺不错,关键都是很直白的API调用,浅显易懂,如果我是技术负责人,我多半是允许员工写这种方式的。

另外如果追求“函数式”,可能可以写成这个样子,实现“一行代码”搞定(效果一样):

bool IsPrivateNetwork2(string ipv4Address) => IPAddress.TryParse(ipv4Address, out _) && (
ipv4Address.StartsWith("192.168.") ||
ipv4Address.StartsWith("10.") ||
ipv4Address.StartsWith("172.") && ipv4Address[6] == '.' && int.Parse(ipv4Address[4..6]) switch
{
var x when x >= 16 && x <= 31 => true,
_ => false
}
);

方法2——使用IPAddress

.NET是个宝库,除了可以使用IPAddress类辅助做验证,实现起来会简单许多:

bool IsPrivateNetwork3(string ipv4Address)
{
if (IPAddress.TryParse(ipv4Address, out var ip))
{
byte[] ipBytes = ip.GetAddressBytes();
if (ipBytes[0] == 10) return true;
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
} return false;
}

该方式的关键是借助IPAddress类的GetAddressBytes()方法,即可非常轻松地完全这个验证——同时代码更简单。

如果追求“函数式”编程,“一行”代码的版本如下(效果相同):

bool IsPrivateNetwork(string ipv4Address) => IPAddress.TryParse(ipv4Address, out var ip) && ip.GetAddressBytes() switch
{
var x when x[0] == 10 => true,
var x when x[0] == 172 && x[1] >= 16 && x[1] <= 31 => true,
var x when x[0] == 192 && x[1] == 168 => true,
_ => false
};

方法3——使用正则表达式

这种挺麻烦的,但也没什么好说的,直接上代码:

bool IsPrivateNetwork(string ipv4Address) => Regex.IsMatch(input, @"(^192\.168\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^172\.([1][6-9]|[2][0-9]|[3][0-1])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)|(^10\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])\.([0-9]|[0-9][0-9]|[0-2][0-5][0-5])$)", RegexOptions.None);

这才是一行代码搞定

不开玩笑,正则表达式性能其实差很多,比以上两种方式差得远——最关键的是,我把这正则表达式写出来,就再也不想维护了

总结

俗话说“条条道路通罗马”,完成一件简单的任务可能会存在不同的办法,但办法与办法之间还是有较大的区别,我觉得重点的是要多写,多比较,多体会。

喜欢的朋友请关注我的微信公众号:【DotNet骚操作】

C#验证IP是否为局域网地址的三种方法的更多相关文章

  1. 【转载】取得系统中网卡MAC地址的三种方法

    From:http://blog.csdn.net/zhangting1987/article/details/2732135 网卡地址这个概念有点混淆不清.因为实际上有两个地址,mac地址和物理地址 ...

  2. Java/JSP获得客户端网卡MAC地址的三种方法解析

    java/jsp获得客户端(IE)网卡MAC地址的方法大概有三种. 1.通过命令方式,在客户端执行Ipconfig 等等.(java/jsp) 2.通过ActiveX的方法.(jsp) 3.通过向13 ...

  3. 获取函数的地址(三种方法,分别是@,Addr,MethodAddress)

    问题来源: http://www.cnblogs.com/del/archive/2008/07/30/1039045.html#1272783 在编译器看来, 重载函数根本就是完全不同的几个函数, ...

  4. 虚拟机下CentOS 配置IP地址的三种方法

    1.自动获取IP地址(我不是用的这种方法,不做过多介绍) 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #if ...

  5. 虚拟机下CentOS 6.5配置IP地址的三种方法

    实验软件环境:虚拟机Vmware Workstation10.0 .CentOS 6.5 32位 1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分 ...

  6. VM虚拟机下CentOS 6.5配置IP地址的三种方法

    1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #ifconfig 查询系统里网卡信息,i ...

  7. CentOS 6.5 配置IP地址的三种方法

    1.自动获取IP地址虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址.#dhclient 自动获取ip地址命令#ifconfig 查询系统里网卡信息,ip地址 ...

  8. C#后台调用浏览器打开下载连接地址的三种方法

    一.从注册表中读取到本地计算机默认浏览器,然后调用下载. private void button1_Click(object sender, EventArgs e)   {       //从注册表 ...

  9. 【转载】VC获取MAC地址的4种方法

    From:http://blog.csdn.net/pdfmaker/article/details/465748 有需求才有创造,有了问题才会想着去解决,那么我这里的获取MAC地址的第4种方法也是在 ...

  10. CentOS 7配置静态IP地址的两种方法 来自:互联网

    CentOS 7配置静态IP地址的两种方法 来自:互联网 时间:2021-01-12 阅读:4 如果你想要为CentOS 7中的某个网络接口设置静态IP地址,有几种不同的方法,这取决于你是否想要使用网 ...

随机推荐

  1. 22.11.20 ICPC合肥站 打星记录

    A,B,H签到. B题:注意区分相对误差与绝对误差!!小数相对误差小于1e-6,至少要输出十二位! G题优先队列.场上十几分钟就想出来了,表扬自己一波,留个坑位写题解. M题情况不多直接暴搜, 最后一 ...

  2. Cloudflare R2 - 免费图床

    前言 之前看了一篇文章,关于介绍 Cloudflare R2 来搭建图床的方案,主要是白嫖 Cloudflare 的空间和 cdn 服务.我现在博客 DevNow 的 CDN 使用的是七牛云,偶尔还是 ...

  3. 【Python】之Mac使用图片识别pytesseract方法报错

    一.前提: python中使用pytesseract图片识别,报错误: pytesseract.pytesseract.TesseractNotFoundError: tesseract is not ...

  4. 为什么要使用Java SPI机制

    Java SPI(Service Provider Interface)最早是在Java SE 6中被引入的,作为一种标准的.用于在运行时发现和加载服务提供者插件的标准机制.以前的程序猿实现JDBC连 ...

  5. Seata 四大模式详解

    分布式事务 参考文章: 分布式事务实战方案汇总 https://www.cnblogs.com/yizhiamumu/p/16625677.html 分布式事务原理及解决方案案例https://www ...

  6. Round #2022/12/10

    问题 D:城市大脑 题目描述 杜老师正在编写杭州城市大脑智能引擎.杭州的道路可以被抽象成为一幅无向图.每条路的初始速度都是 \(1\ m/s\).杜老师可以使用 \(1\) 块钱让任意一条路的速度提升 ...

  7. Mongodb入门1

    学如逆水行舟不进则退 | 心似平原走马易放难追 MongoDB是一个NOSQL类型的数据库,关于SQL与NOSQL的区别不是本文的重点,不在此进行记录. MongoDB安装 然后再将MongoDB的安 ...

  8. 外挂级OCR神器:免费文档解析、表格识别、手写识别、古籍识别、PDF转Word

    TextIn Tools是一款免费的在线OCR工具,支持快速准确的文字和表格识别,手写.古籍识别,提供PDF转Markdown大模型辅助工具,同时支持PDF.WORD.EXCEL.JPG.PPT等各类 ...

  9. 月薪20k以上的软件测试工程师的必备知识点?全部拿走吧!

    我们都知道作为一个软件测试工程师,入门相对比较简单,但是要达到技术精通,甚至薪资能达到20k以上的话,那绝对需要对测试开发有一个系统的了解,以及对这些系统的知识能够熟练掌握. 今天的话是我从阿里以为做 ...

  10. 76.最小覆盖子串 Golang实现

    题目描述: 给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" . 注意: 对于 t ...