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

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

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

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

  1. 10.0.0.0/8,即 10.0.0.010.255.255.255;

  2. 172.16.0.0/12,即 172.16.0.0172.31.255.255;

  3. 192.168.0.0/16,即 192.168.0.0192.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()

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

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骚操作】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法--力扣109题将有序双向链表转换为二叉搜索树

将有序数组转换为二叉搜索树 近一年都比较关注算法相关的知识&#xff0c;也刷了不少题&#xff0c;之前的文章中大多也是算法相关的文章&#xff0c;但是感觉每次遇到树相关的题型都不能应对自如&#xff0c;因此还是有必要在相关知识上下功夫&#xff0c;因此有此次总结&…

[Java基础]字符缓冲流

代码如下: package CopyJavaPack01;import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException;public class CopyJavaDemo04 {public static void main(String[] args) throws IOException {BufferedWriter bw new BufferedWriter(new FileWri…

在C#中使用RESTful API的几种好方法

在C&#xff03;中使用RESTful API的几种好方法原文来自互联网&#xff0c;由长沙DotNET技术社区编译。 通过Web开发的路径&#xff0c;您发现自己迟早需要处理外部API&#xff08;应用程序编程接口&#xff09;。在本文中&#xff0c;我的目标是列出在C&#xff03;项目中使用…

SpringBoot自动装配源码解析

Spring Boot 自动装配原理 使用Spring Boot最方便的一点体验在于我们可以几零配置的搭建一个Spring Web项目&#xff0c;那么他是怎么做到不通过配置来对Bean完成注入的呢。这就要归功于Spring Boot的自动装配实现&#xff0c;他也是Spring Boot中各个Starter的实现基础&#…

自制 .NET Core 路由调试中间件

点击上方蓝字关注“汪宇杰博客”导语本文教大家如何在 .NET Core 应用中使用中间件输出路由信息以便调试程序。背景在 .NET Framework 的上古时代&#xff0c;有个叫做 RouteDebugger 的神器&#xff0c;可以在 MVC 或 Web API 应用中输出当前页面的路由信息&#xff0c;也可查…

玉柴spn码故障对照表_后处理的故障不总是尿素泵故障,也有可能是这些原因

之前说到后处理故障&#xff0c;解决的都是柴油机尿素泵、喷嘴的&#xff0c;而SCR箱同样是一个重要的部件&#xff0c;它的作用就是将尿素液与尾气中的氮氧化物充分混合并发生化学反应的场所&#xff0c;目前重卡SCR箱集SCR催化器和发动机排气消声器与一体。整体材料为不锈钢&…

SpringBoot中Bean按条件装配

Conditional条件装配 Conditional是Spring Framework提供的一个核心功能注解&#xff0c;这个注解的作用是提供自动装配的条件限制&#xff0c;一般我们在用Configuration&#xff0c;Bean的时候使用它。也就是我们在自定义Bean的注入的时候&#xff0c;我们可以通过Condition…

定义一个手表_华米Amazfit Pop评测:一款功能全面的“性价比”手表

目前的智能手表虽然品牌、型号众多&#xff0c;但基本可以分为二种类型&#xff1a;第一种为入门级智能手表&#xff0c;其功能单一与智能手环差不多&#xff0c;但胜在屏幕大、能够带来更好的观感且价格便宜&#xff1b;第二种为旗舰级智能手表&#xff0c;功能全面、硬件水准…

[Java基础]复制文件的异常处理try...catch...finally的做法

代码如下: package ErrorOperatorPack;import java.io.FileReader; import java.io.FileWriter; import java.io.IOException;public class CopyFileDemo01 {public static void main(String[] args){}private static void method() {FileReader fr null;FileWriter fw null…

有哪些你踏入社会才明白的道理

不知不觉已经工作10多年&#xff0c;从一个懵懂的大学生到被社会无情毒打&#xff0c;终于成长一个职场老鸟。最近几天在胡思乱想&#xff0c;这10多年不少认知和感悟&#xff0c;如果10年前有人能告诉我&#xff0c;我会不会少走很多很多弯路&#xff1f;读书的时候&#xff0…

手把手教你 git revert merge

开发中git分支管理 研发流程 从develop分支切出一个新分支&#xff0c;根据是功能还是bug&#xff0c;命名为id-xxx 或 id-fixbug-*。开发者完成开发&#xff0c;提交分支到远程仓库。开发者发起merge请求&#xff0c;将新分支请求merge到develop分支&#xff0c;并提醒code r…

如何把自己的经历写成小说_古天乐的经历教会我们:如何在被欺骗以后改善自己的心理状态...

众所周知&#xff0c;这个只有太阳能黑他的男人&#xff0c;早年未发迹时曾干过泊车小弟等工作&#xff0c;后来作为模特经纪人接触娱乐圈&#xff0c;传闻某次模特迟到&#xff0c;古爷临时救场&#xff0c;算是正式踏入娱圈&#xff0c;出现在无数大牌歌星的MV里&#xff0c;…

从GC的SuppressFinalize方法带你深刻认识Finalize底层运行机制

如果你经常看开源项目的源码&#xff0c;你会发现很多Dispose方法中都有这么一句代码&#xff1a; GC.SuppressFinalize(this); &#xff0c;看过一两次可能无所谓&#xff0c;看多了就来了兴趣&#xff0c;这篇就跟大家聊一聊。一&#xff1a;背景1. 在哪发现的相信现在Mysql在…

NIO工作方式浅析

java Socket 工作机制 Socket是描述计算机之前相互通信的一种抽象功能。通过基于TCP/IP的流套接字协议建立连接A机器B机器通信—建立Socket连接—通过TCP连接&#xff08;端口号指定唯一应用&#xff09;----IP寻址&#xff08;寻找唯一主机&#xff09;----最终找到唯一主机上…

bufferedimage生成的图片模糊_Kaptcha图片验证码工具

阅读文本大概需要3分钟。验证码的作用图片验证码自从诞生以来从未被抛弃&#xff0c;依然发出属于它所应有的光。验证码经常验证如下一些场景。1、用户登录&#xff0c;防止机器人登录2、论坛留言&#xff0c;防止恶意灌水3、短信验证码发送&#xff0c;防止盗刷短信Kaptcha 简…

[Java基础]对象(反)序列化流

对象序列化流: 代码如下: package ObjectOutputStreamPack;import java.io.Serializable;public class Student implements Serializable {private String name;private int age;public Student() {}public Student(String name, int age) {this.name name;this.age age;}pu…

C# 9 新特性:代码生成器、编译时反射

前言今天 .NET 官方博客宣布 C# 9 Source Generators 第一个预览版发布&#xff0c;这是一个用户已经喊了快 5 年特性&#xff0c;今天终于发布了。简介Source Generators 顾名思义代码生成器&#xff0c;它允许开发者在代码编译过程中获取查看用户代码并且生成新的 C# 代码参与…