首页
壁纸
留言板
友链
更多
统计归档
Search
1
TensorBoard:训练日志及网络结构可视化工具
12,588 阅读
2
主板开机跳线接线图【F_PANEL接线图】
7,034 阅读
3
Linux使用V2Ray 原生客户端
6,149 阅读
4
移动光猫获取超级密码&开启公网ipv6
4,682 阅读
5
NVIDIA 显卡限制功率
3,131 阅读
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
登录
/
注册
Search
标签搜索
好物分享
学习笔记
linux
MySQL
nvidia
typero
内网穿透
webdav
vps
java
cudann
gcc
cuda
树莓派
CNN
图像去雾
ssh安全
nps
暗通道先验
阿里云
jupiter
累计撰写
354
篇文章
累计收到
71
条评论
首页
栏目
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
页面
壁纸
留言板
友链
统计归档
搜索到
78
篇与
的结果
2022-01-15
java学习:字符串的格式化及日期时间格式化
1. 常规类型格式化为字符串1.1 转换符转 换 符说 明示 例%s字符串类型"mingrisoft"%c字符类型'm'%b布尔类型true%d整数类型(十进制)99%x整数类型(十六进制)FF%o整数类型(八进制)77%f浮点类型99.99%a十六进制浮点类型FF.35AE%e指数类型9.38e+5%g通用浮点类型(f和e类型中较短的) %h散列码 %%百分比类型%%n换行符 %tx日期与时间类型(x代表不同的日期与时间转换符 1.2.使用案例public static void main(String[] args) { String str=null; str=String.format("Hi,%s", "王力"); System.out.println(str); str=String.format("Hi,%s:%s.%s", "王南","王力","王张"); System.out.println(str); System.out.printf("字母a的大写是:%c %n", 'A'); System.out.printf("3>7的结果是:%b %n", 3>7); System.out.printf("100的一半是:%d %n", 100/2); System.out.printf("100的16进制数是:%x %n", 100); System.out.printf("100的8进制数是:%o %n", 100); System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85); System.out.printf("上面价格的16进制数是:%a %n", 50*0.85); System.out.printf("上面价格的指数表示:%e %n", 50*0.85); System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85); System.out.printf("上面的折扣是%d%% %n", 85); System.out.printf("字母A的散列码是:%h %n", 'A'); }输出结果Hi,王力 Hi,王南:王力.王张 字母a的大写是:A 3>7的结果是:false 100的一半是:50 100的16进制数是:64 100的8进制数是:144 50元的书打8.5折扣是:42.500000 元 上面价格的16进制数是:0x1.54p5 上面价格的指数表示:4.250000e+01 上面价格的指数和浮点数结果的长度较短的是:42.5000 上面的折扣是85% 字母A的散列码是:411.3 搭配的标志标 志说 明示 例结 果+为正数或者负数添加符号("%+d",15)+15−左对齐("%-5d",15)\15 \ 0数字前面补0("%04d", 99)0099空格在整数之前添加指定数量的空格("% 4d", 99)\99\ ,以“,”对数字分组("%,f", 9999.99)9,999.990000(使用括号包含负数("%(f", -99.99)(99.990000)#如果是浮点数则包含小数点,如果是16进制或8进制则添加0x或0("%#x", 99)("%#o", 99)0x63 0143<格式化前一个转换符所描述的参数("%f和%<3.2f", 99.45)99.450000和99.45$被格式化的参数索引("%1$d,%2$s", 99,"abc")99,abc1.4.使用案例public static void main(String[] args) { String str=null; //$使用 str=String.format("格式参数$的使用:%1$d,%2$s", 99,"abc"); System.out.println(str); //+使用 System.out.printf("显示正负数的符号:%+d与%d%n", 99,-99); //补O使用 System.out.printf("最牛的编号是:%03d%n", 7); //空格使用 System.out.printf("Tab键的效果是:% 8d%n", 7); //,使用 System.out.printf("整数分组的效果是:%,d%n", 9989997); //空格和小数点后面个数 System.out.printf("一本书的价格是:% 50.5f元%n", 49.8); }输出结果格式参数$的使用:99,abc 显示正负数的符号:+99与-99 最牛的编号是:007 Tab键的效果是: 7 整数分组的效果是:9,989,997 一本书的价格是: 49.80000元 2. 日期格式化2.1 转换符转 换 符说 明示 例%tx日期与时间类型(x代表不同的日期与时间转换符 c包括全部日期和时间信息星期六 十月 27 14:21:20 CST 2007F“年-月-日”格式2007-10-27D“月/日/年”格式10/27/07r“HH:MM:SS PM”格式(12时制)02:25:51 下午T“HH:MM:SS”格式(24时制)14:28:16R“HH:MM”格式(24时制)14:282.2 使用案例public static void main(String[] args) { Date date=new Date(); //c的使用 System.out.printf("全部日期和时间信息:%tc%n",date); //f的使用 System.out.printf("年-月-日格式:%tF%n",date); //d的使用 System.out.printf("月/日/年格式:%tD%n",date); //r的使用 System.out.printf("HH:MM:SS PM格式(12时制):%tr%n",date); //t的使用 System.out.printf("HH:MM:SS格式(24时制):%tT%n",date); //R的使用 System.out.printf("HH:MM格式(24时制):%tR",date); }输出结果全部日期和时间信息:星期一 九月 10 10:43:36 CST 2012 年-月-日格式:2012-09-10 月/日/年格式:09/10/12 HH:MM:SS PM格式(12时制):10:43:36 上午 HH:MM:SS格式(24时制):10:43:36 HH:MM格式(24时制):10:43public static void main(String[] args) { Date date=new Date(); //b的使用,月份简称 String str=String.format(Locale.US,"英文月份简称:%tb",date); System.out.println(str); System.out.printf("本地月份简称:%tb%n",date); //B的使用,月份全称 str=String.format(Locale.US,"英文月份全称:%tB",date); System.out.println(str); System.out.printf("本地月份全称:%tB%n",date); //a的使用,星期简称 str=String.format(Locale.US,"英文星期的简称:%ta",date); System.out.println(str); //A的使用,星期全称 System.out.printf("本地星期的简称:%tA%n",date); //C的使用,年前两位 System.out.printf("年的前两位数字(不足两位前面补0):%tC%n",date); //y的使用,年后两位 System.out.printf("年的后两位数字(不足两位前面补0):%ty%n",date); //j的使用,一年的天数 System.out.printf("一年中的天数(即年的第几天):%tj%n",date); //m的使用,月份 System.out.printf("两位数字的月份(不足两位前面补0):%tm%n",date); //d的使用,日(二位,不够补零) System.out.printf("两位数字的日(不足两位前面补0):%td%n",date); //e的使用,日(一位不补零) System.out.printf("月份的日(前面不补0):%te",date); }输出结果英文月份简称:Sep 本地月份简称:九月 英文月份全称:September 本地月份全称:九月 英文星期的简称:Mon 本地星期的简称:星期一 年的前两位数字(不足两位前面补0):20 年的后两位数字(不足两位前面补0):12 一年中的天数(即年的第几天):254 两位数字的月份(不足两位前面补0):09 两位数字的日(不足两位前面补0):10 月份的日(前面不补0):103.时间格式化3.1 转换符转 换 符说 明示 例H2位数字24时制的小时(不足2位前面补0)15I2位数字12时制的小时(不足2位前面补0)03k2位数字24时制的小时(前面不补0)15l2位数字12时制的小时(前面不补0)3M2位数字的分钟(不足2位前面补0)03S2位数字的秒(不足2位前面补0)09L3位数字的毫秒(不足3位前面补0)015N9位数字的毫秒数(不足9位前面补0)562000000p小写字母的上午或下午标记中:下午英:pmz相对于GMT的RFC822时区的偏移量+0800Z时区缩写字符串CSTs1970-1-1 00:00:00 到现在所经过的秒数1193468128Q1970-1-1 00:00:00 到现在所经过的毫秒数11934681289843.2 使用案例public static void main(String[] args) { Date date = new Date(); //H的使用 System.out.printf("2位数字24时制的小时(不足2位前面补0):%tH%n", date); //I的使用 System.out.printf("2位数字12时制的小时(不足2位前面补0):%tI%n", date); //k的使用 System.out.printf("2位数字24时制的小时(前面不补0):%tk%n", date); //l的使用 System.out.printf("2位数字12时制的小时(前面不补0):%tl%n", date); //M的使用 System.out.printf("2位数字的分钟(不足2位前面补0):%tM%n", date); //S的使用 System.out.printf("2位数字的秒(不足2位前面补0):%tS%n", date); //L的使用 System.out.printf("3位数字的毫秒(不足3位前面补0):%tL%n", date); //N的使用 System.out.printf("9位数字的毫秒数(不足9位前面补0):%tN%n", date); //p的使用 String str = String.format(Locale.US, "小写字母的上午或下午标记(英):%tp", date); System.out.println(str); System.out.printf("小写字母的上午或下午标记(中):%tp%n", date); //z的使用 System.out.printf("相对于GMT的RFC822时区的偏移量:%tz%n", date); //Z的使用 System.out.printf("时区缩写字符串:%tZ%n", date); //s的使用 System.out.printf("1970-1-1 00:00:00 到现在所经过的秒数:%ts%n", date); //Q的使用 System.out.printf("1970-1-1 00:00:00 到现在所经过的毫秒数:%tQ%n", date); }输出结果2位数字24时制的小时(不足2位前面补0):11 2位数字12时制的小时(不足2位前面补0):11 2位数字24时制的小时(前面不补0):11 2位数字12时制的小时(前面不补0):11 2位数字的分钟(不足2位前面补0):03 2位数字的秒(不足2位前面补0):52 3位数字的毫秒(不足3位前面补0):773 9位数字的毫秒数(不足9位前面补0):773000000 小写字母的上午或下午标记(英):am 小写字母的上午或下午标记(中):上午 相对于GMT的RFC822时区的偏移量:+0800 时区缩写字符串:CST 1970-1-1 00:00:00 到现在所经过的秒数:1347246232 1970-1-1 00:00:00 到现在所经过的毫秒数:1347246232773参考资料Java 字符串格式化详解JAVA字符串格式化-String.format()的使用java字符串格式化(String类format方法)
2022年01月15日
543 阅读
0 评论
0 点赞
2022-01-15
nginx学习:nginx的请求转发算法(负载均衡配置)
1.nginx支持的负载均衡调度算法1.1 轮询(默认算法):每个请求按时间顺序分配到不同后端服务器,如果某个后端服务器宕机,能自动剔除掉。基于iphttp { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { server 192.168.0.161; server 192.168.0.162; server 192.168.0.163; } server { listen 80; location / { proxy_pass http://myweb1; } } }基于域名http { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { server 192.168.0.161; server 192.168.0.162; server 192.168.0.163; } server { listen 80; server_name www.sc.com; location / { proxy_pass http://myweb1; } } }1.2 weight轮询nginx反向代理接受到客户端收到的请求后,可以给不同的后端服务器设置一个权重值(weight),用于调整不同服务器上请求的分配率,权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器配置进行配置的。比如说有些服务器的硬件配置高,比重就会比较大一点。http { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { server 192.168.0.161 weight=1; server 192.168.0.162 weight=3; server 192.168.0.163 weight=6; } server { listen 80; server_name www.sc.com; location / { proxy_pass http://myweb1; } } }1.3 ip_hash每个请求按照发起客户端ip的hash结果进行匹配,这样的算法每一个固定的ip地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下session共享的问题。http { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { ip_hash; server 192.168.0.161; server 192.168.0.162; server 192.168.0.163; } server { listen 80; server_name www.sc.com; location / { proxy_pass http://myweb1; } } }1.4 least-connected–最小连接数将下一个请求分配给活动连接数量最少的服务器http { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { least_conn; server 192.168.0.161; server 192.168.0.162; server 192.168.0.163; } server { listen 80; server_name www.sc.com; location / { proxy_pass http://myweb1; } } }1.5 fair:智能调整调度算法(第三方)动态的根据后端服务器的请求处理器的请求处理响应的时间来进行均衡分配,响应时间短,处理效率高的服务器分配到请求的概率高,响应时间长,处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是nginx默认不支持fair算法,如果要使用这种算法,需要安装upstream_fair模块。1.6 url_hash(第三方)按照访问的url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器,可以在nginx作为静态服务器的情况下提高缓存效率。同样要注意Nginx默认不支持这种调度算法,要使用的话需要安装nginx的hash软件包。http { ..... 其他的内容 #定义上游服务器集群,定义一个负载均衡器 upstream myweb1 { server 192.168.0.161; server 192.168.0.162; server 192.168.0.163; hash $request_uri; } server { listen 80; server_name www.sc.com; location / { proxy_pass http://myweb1; } } }在upstream模块中,可以通过server命令指定后端服务器的IP地址和端口,同时还可以设置每台后端服务器在负载均衡调度中的状态,常用的状态有以下几种:1、down:表示当前server暂时不参与负载均衡。2、backup:预留的备份机,当其他所有非backup机器出现故障或者繁忙的时候,才会请求backup机器,这台机器的访问压力最轻。3、max_fails:允许请求的失败次数,默认为1,配合fail_timeout一起使用4、fail_timeout:经历max_fails次失败后,暂停服务的时间,默认为10s(某个server连接失败了max_fails次,则nginx会认为该server不工作了。同时,在接下来的 fail_timeout时间内,nginx不再将请求分发给失效的server。)参考资料你知道nginx的请求转发算法,如何配置根据权重转发3. nginx的请求转发算法,如何配置根据权重转发Nginx负载均衡调度算法及配置案例Nginx几种负载均衡算法及配置实例Nginx配置之实现多台服务器负载均衡
2022年01月15日
647 阅读
0 评论
0 点赞
2022-01-15
java学习:Junit4单元测试的基本用法及注解和执行顺序
1. Junit最简单的用法案例新建一个类被测试类,里面包含一些测试方法package junit.util; /** * 被测试类,通过Junit对此类的方法进行单元测试 */ public class Claculate { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int divide(int a, int b) { return a / b; } }新建一个Junit的测试类用来测试上面的测试方法,新增Junit的测试类方法如下:package junit.util; import static org.junit.Assert.*; import junit.util.Claculate; import org.junit.Test; /** * junit的测试方法必须使用@Test注解 * 测试方法必须以public void修饰,并且不包含参数 */ public class ClaculateTest { @Test public void testAdd() { /** * assertEquals这个方法是一个断言方法 * 第一个参数表示预期的结果 * 第二个参数表示程序的执行结果 * 当预期结果与执行结果是一致的时候,则表示单元测试成功 */ assertEquals(4, new Claculate().add(1, 3)); } @Test public void testSubtract() { assertEquals(4, new Claculate().subtract(9, 5)); } @Test public void testMultiply() { assertEquals(6, new Claculate().multiply(2, 3)); } @Test(expected=ArithmeticException.class) public void testDivide() { assertEquals(3, new Claculate().divide(9, 0)); } }上面的这个测试类,分别对被测试类Claculate的四个方法进行了测试,测试是选择使用Junit方式进行执行,如果想要执行单个测试方法,可以选择单个方法进行执行2.junit中的常用注解及执行顺序2.1 常用注解为什么引入注解?在实际项目中,进行JUnit测试时,通常会涉及到一些初始化的东西,可能有些配置项需要在测试前进行加载的,JUnit提供了一些初始化的方法用于初始化注解名作用@Before初始化方法,对于每一个测试方法都要执行一次(注意与BeforeClass区别,后者是对于所有方法执行一次)@After释放资源,对于每一个测试方法都要执行一次(注意与AfterClass区别,后者是对于所有方法执行一次)@Test测试方法,在这里可以测试期望异常和超时时间@Ignore忽略的测试方法@BeforeClass针对所有测试,只执行一次,且必须为static void@AfterClass针对所有测试,只执行一次,且必须为static void2.2 执行顺序一个JUnit4的单元测试用例执行顺序为:@BeforeClass -> @Before -> @Test -> @After -> @AfterClass; 每一个测试方法的调用顺序为:@Before -> @Test -> @After; 参考资料junit用法,before,beforeClass,after, afterClass的执行顺序Junit4单元测试的基本用法 Junit的基本使用(详解)
2022年01月15日
764 阅读
0 评论
0 点赞
2022-01-14
[转载]:Java 相关一些面试题
junit 用法,before,beforeClass,after, afterClass 的执行顺序分布式锁nginx 的请求转发算法,如何配置根据权重转发用 hashmap 实现 redis 有什么问题(死锁,死循环,可用 ConcurrentHashmap)线程的状态线程的阻塞的方式sleep 和 wait 的区别hashmap 的底层实现一万个人抢 100 个红包,如何实现(不用队列),如何保证 2 个人不能抢到同一个红包,可用分布式锁java 内存模型,垃圾回收机制,不可达算法两个 Integer 的引用对象传给一个 swap 方法在方法内部交换引用,返回后,两个引用的值是否会发现变化aop 的底层实现,动态代理是如何动态,假如有 100 个对象,如何动态的为这 100 个对象代理是否用过 maven install。 maven test。git(make install 是安装本地 jar 包)tomcat 的各种配置,如何配置 docBasespring 的 bean 配置的几种方式web.xml 的配置spring 的监听器。zookeeper 的实现机制,有缓存,如何存储注册服务的IO 会阻塞吗?readLine 是不是阻塞的用过 spring 的线程池还是 java 的线程池?字符串的格式化方法 (20,21 这两个问题问的太低级了)时间的格式化方法定时器用什么做的线程如何退出结束java 有哪些锁?乐观锁 悲观锁 synchronized 可重入锁 读写锁,用过 reentrantlock 吗?reentrantlock 与 synmchronized 的区别ThreadLocal 的使用场景java 的内存模型,垃圾回收机制为什么线程执行要调用 start 而不是直接 run(直接 run,跟普通方法没什么区别,先调 start,run 才会作为一个线程方法运行)qmq 消息的实现机制 (qmq 是去哪儿网自己封装的消息队列)遍历 hashmap 的三种方式jvm 的一些命令memcache 和 redis 的区别mysql 的行级锁加在哪个位置ConcurrentHashmap 的锁是如何加的?是不是分段越多越好myisam 和 innodb 的区别(innodb 是行级锁,myisam 是表级锁)mysql 其他的性能优化方式linux 系统日志在哪里看如何查看网络进程统计一个整数的二进制表示中 bit 为 1 的个数jvm 内存模型,java 内存模型如何把 java 内存的数据全部 dump 出来如何手动触发全量回收垃圾,如何立即触发垃圾回收hashmap 如果只有一个写其他全读会出什么问题git rebasemongodb 和 hbase 的区别如何解决并发问题volatile 的用途java 线程池(好像之前我的理解有问题)mysql 的 binlog代理模式mysql 是如何实现事务的读写分离何时强制要读主库,读哪个从库是通过什么方式决定的,从库的同步 mysql 用的什么方式mysql 的存储引擎mysql 的默认隔离级别,其他隔离级别将一个链表反转(用三个指针,但是每次只发转一个)spring Aop 的实现原理,具体说说何时会内存泄漏,内存泄漏会抛哪些异常是否用过 Autowire 注解spring 的注入 bean 的方式sql 语句各种条件的执行顺序,如 select, where, order by, group byselect xx from xx where xx and xx order by xx limit xx; 如何优化这个(看 explain)四则元算写代码统计 100G 的 ip 文件中出现 ip 次数最多的 100 个 ipzookeeper 的事物,结点,服务提供方挂了如何告知消费方5 台服务器如何选出 leader (选举算法)适配器和代理模式的区别读写锁static 加锁事务隔离级别门面模式,类图 (外观模式)mybatis 如何映射表结构二叉树遍历主从复制mysql 引擎区别静态内部类加载到了哪个区?方法区class 文件编译后加载到了哪web 的 http 请求如何整体响应时间变长导致处理的请求数变少,该如何处理?用队列,当处理不了那么多 http 请求时将请求放到队列中慢慢处理,web 如何实现队列线程安全的单例模式快速排序性能考虑volatile 关键字用法求表的 size,或做数据统计可用什么存储引擎读多写少可用什么引擎假如要统计多个表应该用什么引擎concurrenhashmap 求 size 是如何加锁的,如果刚求完一段后这段发生了变化该如何处理1000 个苹果放 10 个篮子,怎么放,能让我拿到所有可能的个数可重入的读写锁,可重入是如何实现的?是否用过 NIOjava 的 concurrent 包用过没sting s=new string (“abc”) 分别在堆栈上新建了哪些对象java 虚拟机的区域分配,各区分别存什么分布式事务(JTA)threadlocal 使用时注意的问题(ThreadLocal 和 Synchonized 都用于解决多线程并发访问。但是 ThreadLocal 与 synchronized 有本质的区别。synchronized 是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而 ThreadLocal 为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而 Synchronized 却正好相反,它用于在多个线程间通信时能够获得数据共享)java 有哪些容器 (集合,tomcat 也是一种容器)二分查找算法myisam 的优点,和 innodb 的区别redis 能存哪些类型http 协议格式,get 和 post 的区别可重入锁中对应的 wait 和 notifyredis 能把内存空间交换进磁盘中吗 (这个应该是可以的,但是那个面试官非跟我说不可以)java 线程池中基于缓存和基于定长的两种线程池,当请求太多时分别是如何处理的?定长的事用的队列,如果队列也满了呢?交换进磁盘?基于缓存的线程池解决方法呢?synchronized 加在方法上用的什么锁可重入锁中的 lock 和 trylock 的区别innodb 对一行数据的读会枷锁吗?不枷锁,读实际读的是副本redis 做缓存是分布式存的?不同的服务器上存的数据是否重复?guavacache 呢?是否重复?不同的机器存的数据不同用 awk 统计一个 ip 文件中 top10对表做统计时可直接看 schema info 信息,即查看表的系统信息mysql 目前用的版本公司经验丰富的人给了什么帮助?(一般 boss 面会问这些)自己相对于一样的应届生有什么优势自己的好的总结习惯给自己今后的工作带了什么帮助,举例为证原子类,线程安全的对象,异常的处理方式4 亿个 int 数,如何找出重复的数(用 hash 方法,建一个 2 的 32 次方个 bit 的 hash 数组,每取一个 int 数,可 hash 下 2 的 32 次方找到它在 hash 数组中的位置,然后将 bit 置 1 表示已存在)4 亿个 url,找出其中重复的(考虑内存不够,通过 hash 算法,将 url 分配到 1000 个文件中,不同的文件间肯定就不会重复了,再分别找出重复的)有 1 万个数组,每个数组有 1000 个整数,每个数组都是降序的,从中找出最大的 N 个数,N<1000LinkedHashmap 的底层实现类序列化时类的版本号的用途,如果没有指定一个版本号,系统是怎么处理的?如果加了字段会怎么样?Override 和 Overload 的区别,分别用在什么场景java 的反射是如何实现的参考资料Java 相关一些面试题
2022年01月14日
465 阅读
0 评论
0 点赞
2022-01-13
MySQL学习:常用函数总结
1.数学函数针对数字-- ABS(x) 返回x的绝对值 SELECT ABS(-1); -- 返回1 -- ROUND(x)返回离 x 最近的整数 SELECT ROUND(1.23456); -- 返回1 -- CEIL(x)/CEILING(x) 返回大于或等于 x 的最小整数 SELECT CEIL(1.5); -- 返回2 SELECT CEILING(1.5); -- 返回2 -- FLOOR(x) 返回小于或等于 x 的最大整数 SELECT FLOOR(1.5); -- 返回1 -- POW(x,y)/POWER(x,y)返回 x 的 y 次方 SELECT POW(2,3); -- 返回8 SELECT POWER(2,3); -- 返回8 -- RAND()返回 0 到 1 的随机数 SELECT RAND(); -- SIGN(x)返回 x 的符号,x 是负数、0、正数分别返回 -1、0 和 1 SELECT SIGN(-10); -- 返回-1 -- SQRT(x)返回x的平方根 SELECT SQRT(25); -- 返回5 -- TRUNCATE(x,y)返回数值 x 保留到小数点后 y 位的值,不会进行四舍五入 SELECT TRUNCATE(1.23456,3); -- 返回1.234针对字段-- AVG(expression) 返回一个表达式的平均值,expression 是一个字段 SELECT AVG(age) FROM student; -- MAX(expression)返回字段 expression 中的最大值 SELECT MAX(age) AS maxAge FROM Student; -- MIN(expression)返回字段 expression 中的最大值 SELECT MIN(age) AS minAge FROM Student; -- SUM(expression)返回指定字段的总和 SUM(expression)返回指定字段的总和2.字符串函数-- LENGTH/CHAR_LENGTH(s)/CHARACTER_LENGTH(s)返回字符串 s 的字符数 SELECT LENGTH('1234'); -- 返回4 -- CONCAT(s1,s2…sn)字符串 s1,s2 等多个字符串合并为一个字符串 SELECT CONCAT('hel','llo'); -- 返回hello -- LOCATE(s1,s)从字符串 s 中获取 s1 的开始位置 SELECT LOCATE('st','myteststring'); -- 返回5 -- LCASE(s)/LOWER(s)将字符串 s 的所有字母变成小写字母 SELECT LOWER('RUNOOB'); -- 返回runoob -- UCASE(s)/UPPER(s)将字符串 s 的所有字母变成大写字母 SELECT UCASE('runoob'); -- 返回RUNOOB -- TRIM(s)去掉字符串 s 开始和结尾处的空格 SELECT TRIM(' RUNOOB ');-- 返回RUNOOB -- SUBSTR/SUBSTRING(s, start, length)从字符串 s 的 start 位置截取长度为 length 的子字符串 SELECT SUBSTR/SUBSTRING("RUNOOB", 2, 3);-- 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符,返回UNO -- REVERSE(s)将字符串s的顺序反过来 SELECT REVERSE('abc');-- 返回cba -- REPLACE()替换出现的指定字符串 SELECT REPLACE('狂神说坚持就能成功','坚持','努力'); -- 替换出现的指定字符串 SELECT REPIACE(studentname,'周','邹') FROM student WHERE studentname LIKE '%周';3.时间日期函数-- CURDATE()/CURRENT_DATE()返回当前日期 SELECT CURDATE();-- 返回2019-02-19 SELECT CURRENT_DATE(); -- 返回2019-02-19 -- CURRENT_TIME()/CURTIME()返回当前时间 SELECT CURRENT_TIME(); -- 返回11:40:45 -- NOW()返回当前日期和时间 SELECT NOW();-- 返回2019-02-19 11:41:32 SELECT LOCALTIME(); -- 本地时间 SELECT SYSDATE(); -- 系统时间 -- 提取年月日时分秒 SELECT YEAR(NOW()); SELECT MONTH(NOW()); SELECT DAY(NOW()); SELECT HOUR(NOW()); SELECT MINUTE(NOW()); SELECT SECOND(NOW());4.系统函数-- CURRENT_USER()/SESSION_USER()/SYSTEM_USER()/USER()返回当前用户 SELECT USER(); -- DATABASE()返回当前数据库名 SELECT DATABASE(); -- VERSION()返回数据库的版本号 SELECT VERSION();参考资料MySQL 5.7 参考手册12.6 数值函数和运算符12.8 字符串函数和运算符12.7 日期和时间函数MySQL常用函数大全(总结篇)
2022年01月13日
615 阅读
0 评论
0 点赞
2022-01-13
MySQL学习:SQL关联查询的七种JOIN
1.图示2.案例2.0 准备数据以一个简易问答系统为例,包括问题表和问题所属标签,问题表如下:CREATE TABLE `t_qa` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(200) NOT NULL DEFAULT '' COMMENT '标题', `answer_count` int(5) unsigned NOT NULL DEFAULT '0' COMMENT '回答个数', `label_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '标签id', `create_by` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '创建人', `create_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间', `update_by` bigint(20) unsigned DEFAULT NULL COMMENT '更新人', `update_date` datetime DEFAULT NULL COMMENT '更新时间', `del_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0:不删除,1:删除', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `t_qa` (`id`, `title`, `answer_count`, `label_id`, `create_by`, `create_date`, `update_by`, `update_date`, `del_flag`) VALUES (1, 'Java是什么?', 5, 1, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (2, 'PHP是什么?', 4, 2, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (3, '前端是什么?', 3, 3, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (4, 'nodejs是什么?', 2, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (5, 'css是什么?', 1, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (6, 'JavaScript是什么?', 0, 0, 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0);标签表如下:CREATE TABLE `t_label` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称', `create_by` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '创建人', `create_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间', `update_by` bigint(20) unsigned DEFAULT NULL COMMENT '更新人', `update_date` datetime DEFAULT NULL COMMENT '更新时间', `del_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0:不删除,1:删除', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `t_label` (`id`, `name`, `create_by`, `create_date`, `update_by`, `update_date`, `del_flag`) VALUES (1, 'java', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (2, 'php', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (3, '大前端', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (4, 'mybatis', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (5, 'python', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0), (6, '多线程', 0, '2017-08-24 17:43:53', 0, '2017-08-24 17:43:53', 0);2.1 左连接(LEFT JOIN)问题回答个数标签id标签名称Java是什么?51javaPHP是什么?42php前端是什么?33大前端nodejs是什么?2NULLNULLcss是什么?1NULLNULLJavaScript是什么?1NULLNULLSELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id2.2 右连接(RIGHT JOIN)问题回答个数标签id标签名称Java是什么?51javaPHP是什么?42php前端是什么?33大前端NULLNULL4mybatisNULLNULL5pythonNULLNULL6多线程SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id2.3 内连接(INNER JOIN)问题回答个数标签id标签名称Java是什么?51javaPHP是什么?42php前端是什么?33大前端SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq INNER JOIN t_label tl ON tq.label_id = tl.id2.4 左独有连接(LEFT JOIN)问题回答个数标签id标签名称nodejs是什么?2NULLNULLcss是什么?1NULLNULLJavaScript是什么?0NULLNULLSELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id WHERE tl.id IS NULL2.5 右独有连接(RIGHT JOIN)问题回答个数标签id标签名称NULLNULL4mybatisNULLNULL5pythonNULLNULL6多线程SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id WHERE tq.label_id IS NULL2.6 全连接(FULL JOIN)由于MySQL不支持FULL OUTER JOIN,所以如果有全连接需求时,可用表达式:full outer join = left outer join UNION right outer join来实现。问题回答个数标签id标签名称Java是什么?51javaPHP是什么?42php前端是什么?33大前端nodejs是什么?2NULLNULLcss是什么?1NULLNULLJavaScript是什么?0NULLNULLNULLNULL4mybatisNULLNULL5pythonNULLNULL6多线程SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id UNION SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id 2.7 全连接去交集(FULL JOIN)问题回答个数标签id标签名称nodejs是什么?2NULLNULLcss是什么?1NULLNULLJavaScript是什么?0NULLNULLNULLNULL4mybatisNULLNULL5pythonNULLNULL6多线程SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq LEFT JOIN t_label tl ON tq.label_id = tl.id WHERE tl.id IS NULL UNION SELECT tq.title, tq.answer_count, tl.id, tl.name FROM t_qa tq RIGHT JOIN t_label tl ON tq.label_id = tl.id WHERE tq.label_id IS NULL参考资料一张图看懂 SQL 的各种 JOIN 用法SQL七种JOIN解析【MySQL笔记】七种JOIN的SQL
2022年01月13日
865 阅读
0 评论
0 点赞
2022-01-11
MySQL学习:MySQL常用命令
1.连接MySQL1.1 连接到本机上的MySQLmysql -u root -p # 如果刚安装好MySQL,root是没有密码的1.2 连接到远程主机上的MySQL假设远程主机的IP为:192.168.206.100,用户名为root,密码为12345678。mysql -h 192.168.206.100 -u root -p 12345678; 1.3 退出MySQLexit; # or quit;2. 修改root密码与简单权限管理2.1 修改root密码方法1: 用SET PASSWORD命令mysql -u root mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');方法2:用mysqladminmysqladmin -u root password "newpass" # 如果root已经设置过密码,采用如下方法 mysqladmin -u root password oldpass "newpass"方法3: 用UPDATE直接编辑user表mysql -u root mysql> use mysql; mysql> UPDATE user SET Password = PASSWORD('newpass') WHERE user = 'root'; mysql> FLUSH PRIVILEGES;方法4:在丢失root密码的时候mysqld_safe --skip-grant-tables& mysql -u root mysql mysql> UPDATE user SET password=PASSWORD("new password") WHERE user='root'; mysql> FLUSH PRIVILEGES;2.2 允许用户远程登录允许root使用密码admin123从任何主机连接到mysql服务器GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'admin123' WITH GRANT OPTION; -- 其中"*.*"代表所有资源所有权限, “'root'@%”其中root代表账户名,%代表所有的访问地址,也可以使用一个唯一的地址进行替换,只有一个地址能够访问。如果是某个网段的可以使用地址与%结合的方式,如10.0.42.%。IDENTIFIED BY 'root',这个root是指访问密码。WITH GRANT OPTION允许级联授权。 flush privileges; -- 刷新访问权限表允许用户root使用密码admin123从ip为192.168.12.16的主机连接到mysql服务器GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.1.16' IDENTIFIED BY 'admin123' WITH GRANT OPTION; flush privileges;3.库操作create database db_name; -- 创建数据库 show databases; -- 显示所有的数据库 drop database db_name; -- 删除数据库 use db_name; -- 使用数据库4.表操作建表与删表create table tb_name (字段名 varchar(20), 字段名 char(1)); -- 建表 show tables; -- 显示数据表 desc tb_name; -- 显示表结构 drop table tb_name; -- 删除表eg:-- 创建学生表 create table Student( Sno char(10) primary key, Sname char(20) unique, Ssex char(2), Sage smallint, Sdept char(20) );修改表结构-- 增加字段 alter table table_name add field_name field_type; -- 删除字段 alter table table_name drop field_name; -- 修改字段的注释 alter table `student` modify column `id` comment '学号'; -- 修改原字段名称及类型 alter table table_name change old_field_name new_field_name field_type; -- 加索引 alter table 表名 add index 索引名 (字段名1[,字段名2 …]); -- 删除某个索引 alter table employee drop index emp_name; -- 设置主关键字 alter table 表名 add primary key (字段名); -- 设置唯一限制条件 alter table 表名 add unique 索引名 (字段名); 5.数据操作5.1 插入数据(Add)-- 第一种形式无需指定要插入数据的列名,只需提供被插入的值即可: insert into tb_name values (value1,value2,value3,...); -- 第二种形式需要指定列名及被插入的值: insert into tb_name (column1,column2,column3,...) values (value1,value2,value3,...);eg:insert into Student values ( 20180001,张三,男,20,CS); insert into Student values ( 20180002,李四,男,19,CS); insert into Student (Sno,Sname,Ssex,Sage,Sdept) values ( 20180003,王五,男,18,MA); insert into Student (Sno,Sname,Ssex,Sage,Sdept) values ( 20180004,赵六,男,20,IS);5.2 查询数据(Select)select 语句的一般格式如下:select <目标列表达式列表> [into 新表名] from 表名或视图名 [where <条件>] [group by <分组表达式>] [having <条件>] [order by <排序表达式>[ASC|DESC]]查询所有-- 查询表中所有列 select * from tb_name; -- 查询表中指定的列 select tb_name.<字符型字段>,<字符型字段> ... from tb_name; -- 指定查询结果中的列名 select <字符型字段> as 列标题1,<字符型字段> as 列标题2, <字符型字段> as 列标题3 from bt_name; -- 查询经过计算的列(即表达式的值) select <字符型字段>,<字符型字段>,列标题 = <字符型字段> * n from tb_name;消除查询结果中的重复行select distinct <字符型字段>[,<字符型字段>,...] from tb_name;限制查询结果中的返回行数select top n from tb_name; -- 查询前 n 的数据 select top n percent from tb_name; -- 查询前 n% tb_name的数据对查询结果排序select * from tb_name order by <排序表达式> <排序方法>;查询满足条件的行模板select [all|distinct] [top n[percent]]<目标列表达式列表> from 表名 where <条件>; -- 说明:在查询条件中可使用以下运算符或表达式: -- 比较运算符 <=,<,=,>,>=,!=,<>,!>,!< -- 范围运算符 between... and,not between... and -- 列举运算符 in,not in -- 模糊匹配运算符 like,not like -- 空值运算符 is null,is not null -- 逻辑运算符 and,or,not具体应用-- 使用比较运算符 select * from tb_name where <字段> >= n ; -- 指定范围 select * from tb_name where <字段> [not] between <表达式1> and <表达式2>; -- 使用列举 select * from tb_name where <字段> [not] in(值1,值2,...,值n); -- 使用通配符进行模糊查询 匹配串中通常含有通配符%和_(下划线)。 select * from tb_name where <字符型字段> [not] like <匹配串>; -- 使用null的查询 select * from tb_name where <字符型字段> is [not] null; -- 多重条件查询:使用逻辑运算符 select * from tb_name where <字符型字段> = 'volues' and <字符型字段> > n;使用统计函数-- 求指定的数值型表达式的和或平均值 select avg(<字符型字段>) as 平均数,sum(<字符型字段>) as 总数 from tb_name where <字符型字段> ='字符串'; -- 求指定表达式的最大值或最小值。 select max(<字符型字段>) as 最大值,min(<字符型字段>) as 最小值 from tb_name; -- 统计记录总数。 select count(*) as 总数 from tb_name; -- 统计指定字段值不为空的记录个数 select count(<字符型字段>) as 总数 from tb_name;对查询结果分组-- group by子句用于将查询结果表按某一列或多列值进行分组,列值相等的为一组,每组统计出一个结果。该子句常与统计函数一起使用进行分组统计。格式为: -- group by 分组字段[,...n][having <条件表达式>]; -- 1.在使用group by子句后 -- select列表中只能包含:group by子句中所指定的分组字段及统计函数。 -- 2.having子句的用法 -- having子句必须与group by 子句配合使用,用于对分组后的结果进行筛选(筛选条件中常含有统计函数)。 -- 3. 分组查询时不含统计函数的条件 -- 通常使用where子句;含有统计函数的条件,则只能用having子句。 select <字符型字段>,count(*) as 列标题 from tb_name where <字符型字段>='字符串' group by <字符型字段>;5.3 修改数据(Update)update tb_name set 列名称 = 新值 where 列名称 = 某值;5.4 删除数据(Delete)-- 条件删除 delete from tb_name where 列名称 = 某值; -- 删除所有行 delete * from tb_name; -- 或 delete from tb_name;参考资料mysql修改root密码和设置权限MySQL允许root远程登录MySQL基础 — 常用命令
2022年01月11日
888 阅读
0 评论
0 点赞
2021-12-13
设计模式学习笔记2:单例模式
1.介绍单例模式的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。这种类型的设计模式属于创建型模式。单例模式具有典型的三个特点:只有一个实例。自我实例化。提供全局访问点。应用实例:1、一个班级只有一个班主任。2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。2、避免对资源的多重占用(比如写文件操作)。缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。使用场景:1、要求生产唯一序列号。2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。2.几种实现方式2.1 懒汉式,线程不安全是否 Lazy 初始化:是是否多线程安全:否描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。// 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){} // 2.先定义单例对象但不实例化 private static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ if (lazyMan==null){ lazyMan = new LazyMan(); } return lazyMan; } }2.2 懒汉式,线程安全是否 Lazy 初始化:是是否多线程安全:是描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。优点:第一次调用才初始化,避免内存浪费。缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。// 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){} // 2.先定义单例对象但不实例化 private static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static synchronized LazyMan getInstance(){ if (lazyMan==null){ lazyMan = new LazyMan(); } return lazyMan; } }2.3 饿汉式是否 Lazy 初始化:否是否多线程安全:是描述:这种方式比较常用,但容易产生垃圾对象。优点:没有加锁,执行效率会提高。缺点:类加载时就初始化,浪费内存。// 饿汉式单例模式 public class Hungry { // 1.私有化构造函数 private Hungry(){} // 2.事先创建好对象 private final static Hungry HUNGRY = new Hungry(); // 3.当需要调用的单例对象的时候通过暴露的公有的方法进行调用 public static Hungry getInstance(){ return HUNGRY; } }2.4 双检锁/双重校验锁(DCL,即 double-checked locking)/DCL懒汉式单例是否 Lazy 初始化:是是否多线程安全:是实现难度:较复杂描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。// 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){} // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } }为什么要加volatilelazyMan = new LazyMan(); // 不是一个原子性操作创建对象的过程不是一个原子操作,分为以下3步:1.分配内存空间2.执行构造方法,初始化对象3.把这个对象指向这个空间在执行的过程中可能会发生指令重排的现象,即我们真实想要的执行顺序是1->2->3。但是可能真实的执行顺序是1->3->2。则当线程A以1->3->2的顺序执行到3时,线程B也调用了返回对象实例的方法,则给线程B可能拿到未创建完成的对象进行调用从而导致出错。2.5 登记式/静态内部类是否 Lazy 初始化:是是否多线程安全:是描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }2.6 枚举描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。public enum Singleton { INSTANCE; public void whateverMethod() { } }3.反射下的单例模式3.1 V1:在单例类已经实例化了对象的条件下使用反射破坏单例3.1.1 示例package single; import java.lang.reflect.Constructor; // 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){} // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws Exception { LazyMan instance1 = LazyMan.getInstance(); // 获取空参构造器 Constructor<LazyMan> declareConstructor = LazyMan.class.getDeclaredConstructor(null); // 将空参构造器的Accessible设置为true declareConstructor.setAccessible(true); // 调用空参构造器实例化对象 LazyMan instance2 = declareConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } } single.LazyMan@1b6d3586 single.LazyMan@4554617c3.1.2 防止措施通过在构造函数中加入一个同步代码块进行一次是否已经生成了该单例类对象的判断package single; import java.lang.reflect.Constructor; // 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){ synchronized (LazyMan.class){ if(lazyMan!=null){ throw new RuntimeException("不要试图使用反射破坏单例模式"); } } } // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws Exception { LazyMan instance1 = LazyMan.getInstance(); // 获取空参构造器 Constructor<LazyMan> declareConstructor = LazyMan.class.getDeclaredConstructor(null); // 将空参构造器的Accessible设置为true declareConstructor.setAccessible(true); // 调用空参构造器实例化对象 LazyMan instance2 = declareConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } }Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at single.LazyMan.main(LazyMan.java:38) Caused by: java.lang.RuntimeException: 不要试图使用反射破坏单例模式 at single.LazyMan.<init>(LazyMan.java:11) ... 5 more3.2 V2:V1解决方案破解3.2.1 示例package single; import java.lang.reflect.Constructor; // 懒汉式单例 public class LazyMan { // 1.私有化构造函数 private LazyMan(){ synchronized (LazyMan.class){ if(lazyMan!=null){ throw new RuntimeException("不要试图使用反射破坏单例模式"); } } } // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws Exception { // 获取空参构造器 Constructor<LazyMan> declareConstructor = LazyMan.class.getDeclaredConstructor(null); // 将空参构造器的Accessible设置为true declareConstructor.setAccessible(true); // 调用空参构造器实例化对象 LazyMan instance1 = declareConstructor.newInstance(); LazyMan instance2 = declareConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } }3.2.2 防止措施--"红绿灯策略'',设置标志位package single; import java.lang.reflect.Constructor; // 懒汉式单例 public class LazyMan { private static boolean flag = false; // 1.私有化构造函数 private LazyMan(){ synchronized (LazyMan.class){ if(flag == false){ flag = true; }else{ throw new RuntimeException("不要试图使用反射破坏单例模式"); } } } // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws Exception { // 获取空参构造器 Constructor<LazyMan> declareConstructor = LazyMan.class.getDeclaredConstructor(null); // 将空参构造器的Accessible设置为true declareConstructor.setAccessible(true); // 调用空参构造器实例化对象 LazyMan instance1 = declareConstructor.newInstance(); LazyMan instance2 = declareConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } }3.3 V3:V2解决方案破解3.3.1 示例对字节码进行反编译获取到标志位,然后使用反射破解"红路灯"标志位package single; import java.lang.reflect.Constructor; import java.lang.reflect.Field; // 懒汉式单例 public class LazyMan { private static boolean flag = false; // 1.私有化构造函数 private LazyMan(){ synchronized (LazyMan.class){ if(flag == false){ flag = true; }else{ throw new RuntimeException("不要试图使用反射破坏单例模式"); } } } // 2.先定义单例对象但不实例化 private volatile static LazyMan lazyMan; // 3.当发起调用的时候判断对象是否实例化,如果未实例化,则实例化再返回,否则直接返回 public static LazyMan getInstance(){ // 双重检测锁模式的懒汉式单例 DCL懒汉式 if (lazyMan==null){ synchronized (LazyMan.class){ if (lazyMan==null){ lazyMan = new LazyMan(); } } } return lazyMan; } public static void main(String[] args) throws Exception { // 获取空参构造器 Constructor<LazyMan> declareConstructor = LazyMan.class.getDeclaredConstructor(null); // 将空参构造器的Accessible设置为true declareConstructor.setAccessible(true); // 调用空参构造器实例化对象 LazyMan instance1 = declareConstructor.newInstance(); // 获取"红绿灯标志位" Field flag = LazyMan.class.getDeclaredField("flag"); // 重置为"绿灯" flag.set(instance1,false); LazyMan instance2 = declareConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } }single.LazyMan@4554617c single.LazyMan@74a144823.3.2 防止措施-使用枚举Enum实现单例模式import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; enum EnumSingle { INSTANCE; public EnumSingle getInstance(){ return INSTANCE; } } public class Test{ public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { EnumSingle instance1 = EnumSingle.INSTANCE; Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class); declaredConstructor.setAccessible(true); EnumSingle instance2 = declaredConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); } }Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:417) at single.Test.main(EnumSingle.java:20)参考资料【狂神说Java】单例模式-23种设计模式系列单例模式Java中的双重检查锁(double checked locking) Java设计模式(一)之单例模式
2021年12月13日
624 阅读
0 评论
0 点赞
2021-12-10
设计模式学习笔记1:设计模式概述
1.什么是设计模式设计模式的概念最早是由 克⾥斯托佛·亚历⼭⼤ 在其著作 《建筑模式语⾔》 中⾸次提出的。 该书介绍了城市设计的 “语⾔”,提供了253个描述城镇、邻⾥、住宅、花园、房间及⻄部构造的模式, ⽽此类“语⾔” 的基本单元就是模式。后来, 埃⾥希·伽玛 、 约翰·弗利赛德斯 、 拉尔夫·约翰逊 和 理查德·赫尔姆 这四位大佬即GoF(Gang of Four,四人组/四人帮)接受了模式的概念。 1995 年, 他们出版了 《设计模式: 可复⽤⾯向对象软件的基础》⼀书,将设计模式的概念应⽤到程序开发领域中。该书 共收录了23种设计模式,从此树立了软件设计模式领域的里程碑,人称GoF设计模式。简单来说,设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。2.学习设计模式的意义设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。正确使用设计模式具有以下优点:可以提高程序员的思维能力、编程能力和设计能力。使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。3.设计模式的基本要素4.GoF 23创建型模式:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。结构型模式:适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式行为型模式:模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式。5.OOP七大原则开闭原则:对扩展开放,对修改关闭里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立依赖倒置原则:要面向接口编程,不要面向实现编程。单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性。接口隔离原则:要为各个类建立它们需要的专用接口。迪米特法则:只与你的直接朋友交谈,不跟"陌生人"说话。合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。参考资料【狂神说Java】通俗易懂的23种设计模式教学(停更)设计模式简介
2021年12月10日
540 阅读
0 评论
0 点赞
2021-12-08
AliyunDNSHelper:阿里云dns解析助手-python实现
1.准备工作首先得有一个阿里云的域名https://www.aliyun.com/minisite/goods安装阿里云SDK和其他第三方库pip install aliyun-python-sdk-core-v3 pip install aliyun-python-sdk-domain pip install aliyun-python-sdk-alidns pip install requests获取accessKeyId和accessSecret可以在阿里云控制台个人中心直接获取,但是一般建议使用RAM角色来进行权限控制,这样这个accessKey和accessSecret就只能操作域名,不能操作其他的资源,相对会比较安全。关于RAM快速入门:https://help.aliyun.com/document_detail/28637.html2.代码实现2.1 ali-dns-helper.py`from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest import requests from urllib.request import urlopen import json class AliyunDNSHelper: def __init__(self,accessKeyId = "LTAI4GHqgJgbzPfNnkwyGqks",accessSecret = "CzXkUS8BWcjJ7qEbKrqg6qxUOdnW6M",domain = "4v7p.top"): """ 阿里云DNS助手初始化 需要传入自己的accessKeyId、accessSecret、domain """ self.client = AcsClient(accessKeyId, accessSecret, 'cn-hangzhou') self.domain = domain def update(self,RecordId, RR, Type, Value): """ 修改域名解析记录方法 参数列表: + RecordId:调用查询方法时候查到对应的记录会返回 + RR:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest request = UpdateDomainRecordRequest() request.set_accept_format('json') request.set_RecordId(RecordId) request.set_RR(RR) request.set_Type(Type) request.set_Value(Value) response = self.client.do_action_with_exception(request) def add(self,DomainName, RR, Type, Value): """ 添加新的域名解析记录方法 参数列表: + DomainName:待修改的主域名 + RR:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest request = AddDomainRecordRequest() request.set_accept_format('json') request.set_DomainName(DomainName) request.set_RR(RR) # https://blog.zeruns.tech request.set_Type(Type) request.set_Value(Value) response = self.client.do_action_with_exception(request) def select(self,subDomian): """ 查询子域域名解析记录 参数列表: + subDomian:子域名 """ request = DescribeSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(self.domain) request.set_SubDomain(subDomian + '.' + self.domain) response = self.client.do_action_with_exception(request) # 获取域名解析记录列表 domain_list = json.loads(response) # 将返回的JSON数据转化为Python能识别的 if domain_list["TotalCount"]==0: return None return domain_list["DomainRecords"]["Record"][0] def action(self,subDomian,Value,Type="A"): """ 执行用户关于DNS操作的的行为 参数列表: + action_type操作类型,包括add,update + subDomian:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ print("待处理的记录为 %s:%s-->Domain:%s" % (Type,Value,subDomian + '.' + self.domain)) subDomian_record = self.select(subDomian) if subDomian_record: RecordId,RecordValue = subDomian_record["RecordId"],subDomian_record["Value"] if Value==RecordValue: print("该域名解析记录已存在,跳过") else: self.update(RecordId, subDomian, Type, Value) print("修改域名解析成功") else: self.add(self.domain, subDomian, Type, Value) print("新建域名解析成功") dnsHelper = AliyunDNSHelper(accessKeyId = "LTAI4GHqgJgbzPfNnkwyGqks",accessSecret = "CzXkUS8BWcjJ7qEbKrqg6qxUOdnW6M",domain = "4v7p.top") sub_domain = input("SubDomian:") value = input("value:") sub_domain_type = input("Type:") dnsHelper.action(sub_domain,value,sub_domain_type)2.2 ali-ddns-ipv6.py:实现ipv6 DDNS功能(ipv4同理)2.2.1 获取本机公网ipv6地址方法1:通过http接口获取(推荐)def getIPv6Address(): text = requests.get('https://v6.ident.me').text return text getIPv6Address()'2001:da8:a012:2da:2f0:d2ff:fed0:d0d2'方法2:python执行shell命令--其中的shell命令需要根据实际情况进行修改def get_local_ipv6(): """ 获取本机ipv6地址,其中的shell命令需要根据实际情况进行修改 """ import os; cmd_get_ipv6 = "ifconfig enp1s0 | awk '{if(NR==3){print $3}}'" # 获取本机ipv6的shell命令,需要根据实际情况进行修改 ipv6 = os.popen(cmd_get_ipv6).readlines()[0] if "/" in ipv6: ipv6 = ipv6.split("/")[0] return ipv6 get_local_ipv6()'2001:da8:a012:2da:2f0:d2ff:fed0:d0d2'2.2.2 配合time.sleep完成DDNS功能from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest import requests from urllib.request import urlopen import json import time class AliyunDNSHelper: def __init__(self,accessKeyId = "LTAI4GHqgJgbzPfNnkwyGqks",accessSecret = "CzXkUS8BWcjJ7qEbKrqg6qxUOdnW6M",domain = "4v7p.top"): """ 阿里云DNS助手初始化 需要传入自己的accessKeyId、accessSecret、domain """ self.client = AcsClient(accessKeyId, accessSecret, 'cn-hangzhou') self.domain = domain def update(self,RecordId, RR, Type, Value): """ 修改域名解析记录方法 参数列表: + RecordId:调用查询方法时候查到对应的记录会返回 + RR:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest request = UpdateDomainRecordRequest() request.set_accept_format('json') request.set_RecordId(RecordId) request.set_RR(RR) request.set_Type(Type) request.set_Value(Value) response = self.client.do_action_with_exception(request) def add(self,DomainName, RR, Type, Value): """ 添加新的域名解析记录方法 参数列表: + DomainName:待修改的主域名 + RR:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest request = AddDomainRecordRequest() request.set_accept_format('json') request.set_DomainName(DomainName) request.set_RR(RR) # https://blog.zeruns.tech request.set_Type(Type) request.set_Value(Value) response = self.client.do_action_with_exception(request) def select(self,subDomian): """ 查询子域域名解析记录 参数列表: + subDomian:子域名 """ request = DescribeSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(self.domain) request.set_SubDomain(subDomian + '.' + self.domain) response = self.client.do_action_with_exception(request) # 获取域名解析记录列表 domain_list = json.loads(response) # 将返回的JSON数据转化为Python能识别的 if domain_list["TotalCount"]==0: return None return domain_list["DomainRecords"]["Record"][0] def action(self,subDomian,Value,Type="A"): """ 执行用户关于DNS操作的的行为 参数列表: + action_type操作类型,包括add,update + subDomian:记录名即子域名 + Type:记录类型包括CNAME、A、AAAA等 + Value:记录值 """ print("待处理的记录为 %s:%s-->Domain:%s" % (Type,Value,subDomian + '.' + self.domain)) subDomian_record = self.select(subDomian) if subDomian_record: RecordId,RecordValue = subDomian_record["RecordId"],subDomian_record["Value"] if Value==RecordValue: print("该域名解析记录已存在,跳过") else: self.update(RecordId, subDomian, Type, Value) print("修改域名解析成功") else: self.add(self.domain, subDomian, Type, Value) print("新建域名解析成功") def getIPv6Address(): text = requests.get('https://v6.ident.me').text # 接口失效后需要及时进行修改 return text dnsHelper = AliyunDNSHelper(accessKeyId = "LTAI4GHqgJgbzPfNnkwyGqks",accessSecret = "CzXkUS8BWcjJ7qEbKrqg6qxUOdnW6M",domain = "4v7p.top") sub_domain = "d2550-ipv6" sub_domain_type = "AAAA" while True: print("当前时间:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) value = getIPv6Address() dnsHelper.action(sub_domain,value,sub_domain_type) time.sleep(2*3600) # 每隔2个小时执行1次然后配合screen命令或者去掉无限循环使用定时任务进行执行即可完成ipv6的DDNS的功能参考资料Python实现阿里云域名DDNS支持ipv4和ipv6python 3.7.3 shell_python3执行shell命令的几种方式Python 获取本机公网IPv6地址Python 日期和时间
2021年12月08日
748 阅读
0 评论
0 点赞
2021-10-06
通过SoftEther搭建dns隧道绕过校园网认证进行免费上网
原理介绍工作原理正常情况下,当我们连上酒店或者其他需要验证才可以使用的网络后,虽然上不了网,但是我们的计算机却分配到了IP地址(不分配IP地址web认证就实现不了),此时若我们进行一些上网的操作,那么计算机的数据包将从TCP443端口上发出,校园网、酒店等网关就会拦截从这个端口上发出的数据包。同理从其它端口上发出的数据包也会遭到拦截。但是有一个神奇的端口,从这个端口发出的数据包不会遭到网关拦截,它就是UDP53端口(UDP53端口上运行的协议是DNS协议(域名解析协议))。常见的内网环境中 , 防火墙可能会限制只允许 udp 53 端口出站,这样我们可以利用 DNS 查询流量来封装 TCP 流量 , 达到绕过防火墙的目的。DNS隧道。从名字上来看就是利用DNS查询过程建立起隧道,传输数据。相关软件下载地址SoftEther下载中心https://www.softether-download.com/cn.aspx搭建步骤准备工作一台带宽还可以的云服务器确保服务器ssh连接正常关闭服务器防火墙(云服务器有的需要在安全组里进行二次放行)问题注意:关闭服务器的udp53端口默认运行的程序查看是否关闭$ sudo netstat -ltnup | grep 53 tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 291/systemd-resolve udp 0 0 127.0.0.53:53 0.0.0.0:* 291/systemd-resolve关闭sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved配置1:服务器端完成(ubuntu16.04)下载并运行服务# 下载软件 wget https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/releases/download/v4.38-9760-rtm/softether-vpnserver-v4.38-9760-rtm-2021.08.17-linux-x64-64bit.tar.gz # 解压 tar xzvf softether-vpnserver-v4.38-9760-rtm-2021.08.17-linux-x64-64bit.tar.gz # 编译 cd vpnserver make # 运行 ./vpnserver start初始化工作(除了输入1次1之外,其余均按回车) ./vpncmd vpncmd command - SoftEther VPN Command Line Management Utility SoftEther VPN Command Line Management Utility (vpncmd command) Version 4.38 Build 9760 (English) Compiled 2021/08/17 22:32:49 by buildsan at crosswin Copyright (c) SoftEther VPN Project. All Rights Reserved. By using vpncmd program, the following can be achieved. 1. Management of VPN Server or VPN Bridge 2. Management of VPN Client 3. Use of VPN Tools (certificate creation and Network Traffic Speed Test Tool) Select 1, 2 or 3: 1 Specify the host name or IP address of the computer that the destination VPN Server or VPN Bridge is operating on. By specifying according to the format 'host name:port number', you can also specify the port number. (When the port number is unspecified, 443 is used.) If nothing is input and the Enter key is pressed, the connection will be made to the port number 8888 of localhost (this computer). Hostname of IP Address of Destination: If connecting to the server by Virtual Hub Admin Mode, please input the Virtual Hub name. If connecting by server admin mode, please press Enter without inputting anything. Specify Virtual Hub Name: Connection has been established with VPN Server "localhost" (port 443). You have administrator privileges for the entire VPN Server. VPN Server>配置2:客户端完成(win10)下载SoftEther VPN Server Manager并安装添加新的连接设置(主机名写服务器的IP或者域名)-第一次连接会让你设置新密码继续完成配置添加用户开启虚拟NAT和虚拟DHCP开启DNS 53端口监听连接测试下载客户端并安装添加新连接连接设置名随便填主机名填服务IP端口号填53连接测试,获取到IP则代表搭建无误参考资料1.SoftEther下载中心
2021年10月06日
1,590 阅读
0 评论
0 点赞
2021-10-04
通过dns2tcp搭建tcp隧道绕过校园网认证进行免费上网
原理介绍dns2tcp工作原理正常情况下,当我们连上酒店或者其他需要验证才可以使用的网络后,虽然上不了网,但是我们的计算机却分配到了IP地址(不分配IP地址web认证就实现不了),此时若我们进行一些上网的操作,那么计算机的数据包将从TCP443端口上发出,校园网、酒店等网关就会拦截从这个端口上发出的数据包。同理从其它端口上发出的数据包也会遭到拦截。但是有一个神奇的端口,从这个端口发出的数据包不会遭到网关拦截,它就是UDP53端口(UDP53端口上运行的协议是DNS协议(域名解析协议))。常见的内网环境中 , 防火墙可能会限制只允许 udp 53 端口出站,这样我们可以利用 DNS 查询流量来封装 TCP 流量 , 达到绕过防火墙的目的。DNS隧道。从名字上来看就是利用DNS查询过程建立起隧道,传输数据。dns2tcp工具介绍dns2tcp 是一个使用C语言开发的利用DNS隧道转发TCP连接的工具。客户端会在本地监听一个端口,并指定:要使用服务端上面的哪个资源(如ssh、socket、http)我们只需把数据扔进本地的该端口,dns2tcpc将使用DNS隧道传送到服务端。随后,服务端根据客户端指定要使用的资源,将数据转发到其本机的相应端口中去。这里的相应端口,可通过配置文件(/etc/dns2tcpd.conf)配置。准备工作判断DNS解析的53端口是否开放连接校园网,测速在未认证状态下是否可以正常dns解析$ nslookup www.baidu.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 110.242.68.3 Name: www.a.shifen.com Address: 110.242.68.4可以看到,nslookup解析域名正常,代表DNS解析的53端口正常开放,从这个端口发出的数据包不会遭到网关拦截 ,也就是UDP53端口。云服务器与域名具有公网ip的云服务1台域名一个搭建步骤(ubuntu16.04为例)设置域名解析登录你的域名服务器商如:DNSpod在域名下面添加一个A记录,A记录的名字可以任意,如ns1.vvvtimes.com,A记录的值为你VPS服务器的IP地址。最后,再添加一个NS记录,这个NS的名字可以任意,比如tcp.vvvtimes.com,NS记录的值为你上面添加的A记录的名字,即ns1.vvvtimes.com。服务器端安装DNS2TCPsudo apt update sudo apt install dns2tcp编辑DNS2TCP配置文件在 /etc 建立一个名为 dns2tcpd.conf 的文件, 然后输入以下配置:listen = 0.0.0.0 port = 53 user = nobody chroot = /tmp domain = tcp.vvvtimes.com(上面配置NS记录的域名) key = fuckoff (密码,可选) resources = ssh:127.0.0.1:22,socks:127.0.0.1:1082,http:127.0.0.1:3128 启动 DNS2TCP(建议使用screen启动)dns2tcpd -f /etc/dns2tcpd.conf -F -d 2 注意:腾讯云服务器不给实际网卡分配公网IP,所以要监听0.0.0.0客户端安装DNS2TCPsudo apt update sudo apt install dns2tcp启动 DNS2TCP(建议使用screen启动)dns2tcpc -c -k fuckoff -r ssh -z tcp.vvvtimes.com 1.2.3.4 -l 2222 -d 2 -k 后接密码,与服务器端的配置保持一致即可 -r 后接服务名称, 这里我们用ssh -z 后接NS记录的网址, ip, 注意IP地址最好写上, 可以不写 -l 后接本地端口 -d 开启 Debug测试ssh连接测试ssh root@127.0.0.1 -p 2222可以直接登陆你的server ssh。设置ssh隧道(偶尔会提示reset peer或许要多试几次):ssh -CfNg root@127.0.0.1 -p 2222 -D 7002查看端口是否开放$ lsof -i:2222 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME dns2tcpc 28938 bonelee 4u IPv4 11154775 0t0 TCP localhost:2222 (LISTEN) dns2tcpc 28938 bonelee 5u IPv4 11157735 0t0 TCP localhost:2222->localhost:46296 (ESTABLISHED) ssh 28953 bonelee 3u IPv4 11157734 0t0 TCP localhost:46296->localhost:2222 (ESTABLISHED) $ lsof -i:7002 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ssh 28953 bonelee 4u IPv4 11160083 0t0 TCP *:afs3-prserver (LISTEN) ssh 28953 bonelee 5u IPv6 11160084 0t0 TCP *:afs3-prserver (LISTEN)浏览器里直接socks5代理127.0.0.1 7002端口即可上网了!上谷歌也是可以的。。。不过速度就不咋地。。。参考资料通过dns2tcp绕过校园网认证进行免费上网[DNS隧道之DNS2TCP实现——dns2tcpc必须带server IP才可以,此外ssh可以穿过墙的,设置代理上网]使用DNS2TCP搭建DNS隧道,绕过网络认证,实现免验证上网
2021年10月04日
1,345 阅读
0 评论
0 点赞
2021-07-30
linux iperf 局域网测速
linux iperf 局域网测速iperf 百科描述Iperf 是一个网络性能测试工具。Iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽、延迟抖动和数据包丢失iperf使用1.服务端启动服务,作为server:sudo apt-get install iperf iperf -s -i 2 # 每两秒间隔输出测试结果2.客户端启动服务,作为client:sudo apt-get install iperf iperf -c <server_IP> -t 10iperf 结果分析每两秒输出的结果 Transfer是数据量,Bandwidth是这些数据量的传输时的速度Server listening on TCP port 5001 TCP window size: 128 KByte (default) ------------------------------------------------------------ [ 4] local 192.168.0.120 port 5001 connected with 192.168.0.233 port 56144 [ ID] Interval Transfer Bandwidth [ 4] 0.0- 2.0 sec 22.3 MBytes 93.7 Mbits/sec [ 4] 2.0- 4.0 sec 22.4 MBytes 94.1 Mbits/sec [ 4] 4.0- 6.0 sec 22.4 MBytes 94.2 Mbits/sec [ 4] 6.0- 8.0 sec 22.4 MBytes 94.1 Mbits/sec [ 4] 8.0-10.0 sec 22.4 MBytes 94.1 Mbits/sec [ 4] 0.0-10.0 sec 113 MBytes 94.1 Mbits/sec参考资料1.arm linux iperf 局域网测速:https://blog.csdn.net/shenhuxi_yu/article/details/111612609
2021年07月30日
701 阅读
0 评论
0 点赞
2021-02-20
python实现阿里云域名ipv4和ipv6 ddns
1.前言首先得有一个阿里云的域名:https://www.aliyun.com/minisite/goods?userCode=jdjc69nf然后你的IP必须是公网IP,不然解析了也没用。本文章讲怎样通过阿里云的SDK来添加修改域名解析,检查本机IP与解析的IP是否一致,不一致自动修改解析,达到动态解析的目的,主要用于家庭宽带这些动态IP的地方。2.安装阿里云SDK和其他第三方库pip install aliyun-python-sdk-core-v3 pip install aliyun-python-sdk-domain pip install aliyun-python-sdk-alidns pip install requests3.获取accessKeyId和accessSecret可以在阿里云控制台个人中心直接获取,但是一般建议使用RAM角色来进行权限控制,这样这个accessKey和accessSecret就只能操作域名,不能操作其他的资源,相对会比较安全。关于RAM快速入门:https://help.aliyun.com/document_detail/28637.html?source=5176.11533457&userCode=jdjc69nf4.源码下载-官方4.1 下载地址gitee:https://gitee.com/zeruns/aliddns_Pythongithub:https://github.com/zeruns/-Python-aliddns_ipv4-ipv6将aliddns.py文件下载下来。然后用notepad++或其他编辑器打开,按照注释提示修改并保存。然后运行一下看看有没有问题:打开cmd输入python 脚本目录4.2源码备份from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest import requests from urllib.request import urlopen import json ipv4_flag = 1 # 是否开启ipv4 ddns解析,1为开启,0为关闭 ipv6_flag = 1 # 是否开启ipv6 ddns解析,1为开启,0为关闭 accessKeyId = "accessKeyId" # 将accessKeyId改成自己的accessKeyId accessSecret = "accessSecret" # 将accessSecret改成自己的accessSecret domain = "4v7p.top" # 你的主域名 name_ipv4 = "ipv4.test" # 要进行ipv4 ddns解析的子域名 name_ipv6 = "ipv6.test" # 要进行ipv6 ddns解析的子域名 client = AcsClient(accessKeyId, accessSecret, 'cn-hangzhou') def update(RecordId, RR, Type, Value): # 修改域名解析记录 from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest request = UpdateDomainRecordRequest() request.set_accept_format('json') request.set_RecordId(RecordId) request.set_RR(RR) request.set_Type(Type) request.set_Value(Value) response = client.do_action_with_exception(request) def add(DomainName, RR, Type, Value): # 添加新的域名解析记录 from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest request = AddDomainRecordRequest() request.set_accept_format('json') request.set_DomainName(DomainName) request.set_RR(RR) # https://blog.zeruns.tech request.set_Type(Type) request.set_Value(Value) response = client.do_action_with_exception(request) if ipv4_flag == 1: request = DescribeSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(domain) request.set_SubDomain(name_ipv4 + '.' + domain) response = client.do_action_with_exception(request) # 获取域名解析记录列表 domain_list = json.loads(response) # 将返回的JSON数据转化为Python能识别的 ip = urlopen('https://api-ipv4.ip.sb/ip').read() # 使用IP.SB的接口获取ipv4地址 ipv4 = str(ip, encoding='utf-8') print("获取到IPv4地址:%s" % ipv4) if domain_list['TotalCount'] == 0: add(domain, name_ipv4, "A", ipv4) print("新建域名解析成功") elif domain_list['TotalCount'] == 1: if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv4.strip(): update(domain_list['DomainRecords']['Record'][0]['RecordId'], name_ipv4, "A", ipv4) print("修改域名解析成功") else: # https://blog.zeruns.tech print("IPv4地址没变") elif domain_list['TotalCount'] > 1: from aliyunsdkalidns.request.v20150109.DeleteSubDomainRecordsRequest import DeleteSubDomainRecordsRequest request = DeleteSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(domain) # https://blog.zeruns.tech request.set_RR(name_ipv4) response = client.do_action_with_exception(request) add(domain, name_ipv4, "A", ipv4) print("修改域名解析成功") print("本程序版权属于zeruns,博客:https://blog.zeruns.tech") if ipv6_flag == 1: request = DescribeSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(domain) request.set_SubDomain(name_ipv6 + '.' + domain) response = client.do_action_with_exception(request) # 获取域名解析记录列表 domain_list = json.loads(response) # 将返回的JSON数据转化为Python能识别的 ip = urlopen('https://api-ipv6.ip.sb/ip').read() # 使用IP.SB的接口获取ipv6地址 ipv6 = str(ip, encoding='utf-8') print("获取到IPv6地址:%s" % ipv6) if domain_list['TotalCount'] == 0: add(domain, name_ipv6, "AAAA", ipv6) print("新建域名解析成功") elif domain_list['TotalCount'] == 1: if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv6.strip(): update(domain_list['DomainRecords']['Record'][0]['RecordId'], name_ipv6, "AAAA", ipv6) print("修改域名解析成功") else: # https://blog.zeruns.tech print("IPv6地址没变") elif domain_list['TotalCount'] > 1: from aliyunsdkalidns.request.v20150109.DeleteSubDomainRecordsRequest import DeleteSubDomainRecordsRequest request = DeleteSubDomainRecordsRequest() request.set_accept_format('json') request.set_DomainName(domain) request.set_RR(name_ipv6) # https://blog.zeruns.tech response = client.do_action_with_exception(request) add(domain, name_ipv6, "AAAA", ipv6) print("修改域名解析成功")6.设置定时任务6.1 Linux操作使用crontab -e写入定时任务即可。例如:6.2 windows操作右键点击电脑左下角,再点击计算机管理点击任务计划程序,再点击创建任务,输入要设置的任务名称。新建触发器,执行间隔可以自己设置,持续时间改成无限期。新建操作,这一步很重要,配置错误就会导致脚本文件执行不成功!!!最后确认就行。参考资料Python实现阿里云域名DDNS支持ipv4和ipv6:https://developer.aliyun.com/article/755182
2021年02月20日
814 阅读
0 评论
0 点赞
2021-01-16
CentOS7设置上网代理
CentOS设置上网代理1、网页上网网页上网设置代理很简单,在firefox浏览器下 Edit-->>Preferences-->>Advanced-->>Network在Connection下点击Settings,里面的manual proxy configuration里设置IP和PORT即可,2、系统环境代理设置设置全局代理修改 /etc/profile 文件,添加下面内容:http_proxy=http://username:password@yourproxy:8080/ https_proxy=https://username:password@yourproxy:8080/ export http_proxy export https_proxy如果没有密码限制,则以上内容可以修改为以下内容:http_proxy=http://yourproxy:8080/ https_proxy=https://yourproxy:8080/ export http_proxy export https_proxy针对某个用户设置代理只修改 ~/.bash_profile 文件,文件内容与上面的 /etc/profile 相同http_proxy=http://username:password@yourproxy:8080/ https_proxy=https://username:password@yourproxy:8080/ export http_proxy export https_proxy如果没有密码限制,则以上内容可以修改为以下内容:http_proxy=http://yourproxy:8080/ https_proxy=https://yourproxy:8080/ export http_proxy export https_proxy3、设置yum 的代理对于 yum 的代理,还要另外设置 /etc/yum.conf 文件vi /etc/yum.conf 添加以下代码:http_proxy=http://username:password@yourproxy:8080/ #若无密码限制,则为以下方式 http_proxy=http://yourproxy:8080/4、wget代理设置编辑文件为:/etc/wgetrcvi /etc/wgetrc添加下面两行:http_proxy=http://username:password@yourproxy:8080/ https_proxy=https://username:password@yourproxy:8080/ #若无密码限制,则为以下方式 http_proxy=http://yourproxy:8080/ https_proxy=https://yourproxy:8080/参考资料CentOS设置网络代理:https://blog.csdn.net/u013063153/article/details/78120945CentOS设置上网代理:https://blog.csdn.net/bohenzong1654/article/details/100964835?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-1.control
2021年01月16日
761 阅读
0 评论
0 点赞
1
...
4
5
6