SOCKET简介

Socket英文原义是 孔 或 插座。作为进程通信机制,取后一种意思。通常也称作 套接字,用于描述IP地址和端口,是一个通信链的句柄(其实就是两个程序通信用的)。

以一个电话网为例:

  • (1), 电话的通话双方相当于相互通信的2个程序,电话号码就是ip地址。
  • (2),任何用户在通话之前,首先要占有一部电话机,相当于申请一个Socket;同时要知道对方的号码,相当于对方有一个固定的Socket。
  • (3),然后向对方拨号呼叫,相当于发出连接请求。对方假如在场并空闲,拿起电话话筒,双方就可以正式通话,相当于连接成功。
  • (4),双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向Socket发送数据和从Socket接收数据。
  • (5),通话结束后,一方挂起电话机相当于关闭Socket,撤销连接。

套接字分类

为了满足不同程序对通信质量和性能的要求,一般的网络系统都提供了以下3种不同类型的套接字,以供用户在设计程序时根据不同需要来选择:

  • 流式套接字(SOCK_STREAM):提供了一种可靠的、面向连接的双向数据传输服务。实现了数据无差错,无重复的发送,内设流量控制,被传输的数据被看做无记录边界的字节流。在TCP/IP协议簇中,使用TCP实现字节流的传输,当用户要发送大批量数据,或对数据传输的可靠性有较高要求时使用流式套接字。
  • 数据报套接字(SOCK_DGRAM):提供了一种无连接、不可靠的双向数据传输服务。数据以独立的包形式被发送,并且保留了记录边界,不提供可靠性保证。数据在传输过程中可能会丢失或重复,并且不能保证在接收端数据按发送顺序接收。在TCP/IP协议簇中,使用UDP实现数据报套接字。
  • 原始套接字(SOCK_RAW):该套接字允许对较低层协议(如IP或ICMP)进行直接访问。一般用于对TCP/IP核心协议的网络编程。
    阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
user  nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name www.shiyx.top;
return 301 https://www.shiyx.top$request_uri;
server_tokens off;
}
upstream app_servers {
server dockerwebapp:5000;
}
server {
listen 443 ssl http2;
ssl on;
server_name www.shiyx.top;
#$host该变量的值等于请求头中Host的值。如果Host无效时,那么就是处理该请求的server的名称。
#permanent: 永久性重定向。请求日志中的状态码为301
#nginx 对文档检测比较严格,所以if ( $host != 'www.csdn.com' ) 这些代码之间需要有空格隔开,不然会
#报错:unknown directive “if($host!=”
if ($host != 'www.shiyx.top' ){
rewrite ^/(.*)$ https://www.shiyx.top/$1 permanent;
}
ssl_certificate /etc/letsencrypt/live/shiyx.top/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/shiyx.top/privkey.pem;

#禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
# 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,
#和off差不多,停用缓存。如shared:SSL:10m表示我>所有的nginx工作进程共享ssl会话缓存,
#网介绍说1M可以存放约4000个sessions。
ssl_session_cache shared:SSL:1m;

# 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_session_timeout 5m;

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;

# 选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。
# 这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'
#(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_ciphers HIGH:!aNULL:!MD5;

# 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
ssl_prefer_server_ciphers on;

# 查看代理程序的ip
# sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>
location / {
proxy_pass http://app_servers;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_cache_bypass $http_upgrade;
}
location ~ /.well-known{
allow all;
}
}
}

1
2
3
4
5
6
location / {
root D:\项目部署\web;
index index.html index.htm;
## 添加以下代码
try_files $uri $uri/ /index.html;
}

DNS

dns端口号是域名系统 (Domain Name System) 的缩写,该系统用于命名组织到域层次结构中的计算机和网络服务。在Internet上域名与IP地址之间是一一对应的,域名虽然便于人们记忆,但机器之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成。

DNS协议运行在UDP协议之上,使用端口号53。在传输层TCP提供端到端可靠的服务,在UDP端提供尽力交付的服务。其控制端口作用于UDP端口53。

缺点:

传统的DNS查询和应答采用大都采用UDP明文传输,存在网络监听、DNS劫持、中间设备干扰的风险。

从安全角度来看,请求传输时通常不进行任何加密,任何人都可以读取的 DNS 其实是不安全的。这意味着网络罪犯可以很容易地使用自己的服务器拦截受害者的 DNS,将用户的请求跳转到钓鱼网站上,这些网站发布恶意软件,或在正常网站上投放大量广告吸引用户,这种行为我们称之为 DNS 劫持。

DoT

DoT 全称是 DNS over TLS,它使用 TLS 协议来传输 DNS 协议。TLS 协议是目前互联网最常用的安全加密协议之一,我们访问 HTTPS 的安全基础就是基于 TLS 协议的。相比于之前使用无连接无加密的 UDP 模式, TLS 本身已经实现了保密性与完整性。

DoH

DoH 全称是 DNS over HTTPS,它使用 HTTPS 来传输 DNS 协议。DoH 的安全原理与 DoT 一样,他们之间的区别只在于:DoH 有了 HTTP 格式封装,更加通用。

区别

DoT 在专用端口上通过 TLS 连接 DNS 服务器,而 DoH 是基于使用 HTTP 应用程序层协议,将查询发送到 HTTPS 端口上的特定 HTTP 端点,这里造成的外界感知就是端口号的不同,DoT 的端口号是 853DoH 端口号 443

A

A记录: 将域名指向一个IPv4地址(例如:100.100.100.100),需要增加A记录。

1
2
example.com     A       12.34.56.78
hello.example.com A 12.34.56.78

可以将不同的子域指向不同的 IP 地址。如果要将 example.com 的每个子域都指向同一个 IP,可以使用星号(*)作为子域:

1
*.example.com   A       12.34.56.78

AAAA

一个 AAAA 记录和 A 记录相似,不过是用于 IPv6 的 IP 地址。一个典型的 AAAA 记录如下所示:

1
example.com     AAAA        0123:4567:89ab:cdef:0123:4567:89ab:cdef

NS

NS记录: 域名解析服务器记录(Name sever record),是为域或子域设置对应的域名服务器。
如果要将子域名指定某个域名服务器来解析,需要设置NS记录。

域名的主要域名服务器记录既可以在注册商处设置,也可以在自己的区域文件中设置。一份典型的域名服务器记录(至少需要两个记录)如下所示:NS 记录的顺序无关紧要。DNS 请求随机发送到不同的服务器,如果一个主机无法响应,将查询另外一个主机。

1
2
3
4
5
example.com     NS      ns1.linode.com.
example.com NS ns2.linode.com.
example.com NS ns3.linode.com.
example.com NS ns4.linode.com.
example.com NS ns5.linode.com.

CNAME

CNAME 记录:称为规范名称记录(Canonical Name record),它将一个域或子域匹配到其它不同的域。
如果将域名指向一个域名,实现与被指向域名相同的访问效果,需要增加CNAME记录。
通过 CNAME 记录,DNS 查找则采用目标域的 DNS 解析作为别名的解析。下面举例:

1
2
alias.com       CNAME   example.com.
example.com A 12.34.56.78

SOA

SOA记录: 起始权限记录(Start of Authority record),起始授权机构记录,NS用于标识多台域名解析服务器,SOA记录用于在众多NS记录中哪一台是主服务器。

SOA 记录中提到的单个域名服务器被视为动态 DNS 的第一服务器,并且是将区域文件传播到所有其他域名服务器之前,区域文件就要被更改完成的所在。

SOA 记录:

1
@   IN  SOA ns1.linode.com. admin.example.com. 2013062147 14400 14400 1209600 86400

注意:管理电子邮件地址使用句点(.)而不是 @ 符号编写。

含义:

  • 序列号:此域的区域文件的修订号。它在文件更新时会发生变化。
  • 刷新时间:辅助 DNS 服务器在检查更改之前保留区域文件的时间(以秒为单位)。
  • 重试时间:辅助 DNS 服务器在重试传输失败的区域文件之前需要等待的时间。
  • 过期时间:辅助 DNS 服务器无法自行更新时,当前区域文件副本失效之前所等待的时间。
  • 最短 TTL:其他服务器应从该区域文件中保留缓存数据的最短时间。

WKS

WKS:众所周知的业务描述

CAA

DNS 证书颁发机构授权(CAA,Certification Authority Authorization)使用 DNS 来允许域的持有者指定 “哪些证书颁发机构能够为该域发放证书”。

AXFR

AXFR 记录是一种用于 DNS 复制的记录(虽然当下有更先进的 DNS 复制方法)。AXFR 记录不是用于普通区域文件的。相反,它们应用于从 DNS 服务器,作用是从主 DNS 服务器上复制区域文件。

PTR

PTR记录: PTR记录是A记录的逆向记录,又称做IP反查记录或指针记录,负责将IP反向解析为域名。

PTR 记录或称指针记录(Pointer record)将 IP 地址匹配至一个域或者子域,它允许反向的 DNS 查询工作。它执行的服务于 A 记录截然相反,因为它允许您查找与特定 IP 地址相关联的域。

添加 PTR 记录,需要创建一个有效且实时的 A 或 AAAA 记录,将所需的域指向该 IP。如果需要 IPv4 PTR 记录,请将域或子域指向IPv4 地址。如果需要 IPv6 PTR 记录,则将域指向IPv6 地址。除此之外,IPv4 和 IPv6 PTR 记录的工作方式是相同的。

MX

MX记录:邮件交换记录(Mail exchanger record),建立电子邮箱服务,将指向邮件服务器地址,需要设置MX记录。建立邮箱时,一般会根据邮箱服务商提供的MX记录填写此记录。

1
2
example.com         MX      10  mail.example.com.
mail.example.com A 12.34.56.78

以上记录将example.com的邮件直接发送到mail.example.com这一服务器。目标域(上述的mail.example.com)需要有自己的 A 记录。理想情况下,MX 记录应指向同为其服务器主机名的域。

优先级是 MX 记录的另一个组成部分。这是记录类型和目标服务器之间写入的数字(在上例中为 10)。优先级允许您为特定域的邮件指定一个回退服务器(或多个服务器)。较低的数字代表较高的优先级。

下面是具有两个回退邮件服务器的域的示例:

1
2
3
example.com         MX      10  mail_1.example.com
example.com MX 20 mail_2.example.com
example.com MX 30 mail_3.example.com

在此示例中,如果 mail_1.example.com 已关闭,则将传递邮件到 mail_2.example.com。如果mail_2.example.com 也是关闭,邮件将被发送到 mail_3.example.com

TXT

可任意填写,可为空。一般做一些验证记录时会使用此项,如:做SPF(反垃圾邮件)记录。

TXT记录或称文本记录(Text record),向因特网上的其他资源提供有关该域的信息。它是一种灵活的 DNS 记录类型,可根据具体内容提供多种用途。TXT 记录的一个常见用途是在域名服务器上创建 SPF 记录

SPF

SPF 记录或称发送方政策框架记录(Sender Policy Framework record),列出了域或子域所指定的邮件服务器。它有助于确定邮件服务器的合法性,并减少欺骗的可能性(当有人伪造电子邮件的标题,使其看起来像是来自您的域时)。垃圾邮件发送者有时会尝试这样做以绕过过滤器。

DKIM

DKIM 记录或称域名密匙确认邮件记录(Domainkeys Identified Mail record),它显示用于验证已经签署了 DKIM 协议的消息的公钥。这种做法提高了检查邮件可靠性的能力。一个典型的 DKIM 记录如下所示:

1
selector1._domainkey.example.com        TXT     k=rsa;p=J8eTBu224i086iK

DKIM 记录以文本记录作为实现。该记录必须是为子域创建的记录,它具有唯一对应于键的一个选择器,然后便是句点(.),紧跟着是_domainkey.example.com。其类型为 TXT,值则包含键的类型,后面跟着实际键值。

SRV

SRV记录: 添加服务记录服务器服务记录时会添加此项,SRV记录了哪台计算机提供了哪个服务。格式为:服务的名字.协议的类型(例如:_example-server._tcp)。

SRV 记录或称服务记录(Service record)将运行在您的域或子域上的指定服务匹配到一个目标与。这允许您将特定服务(如即时消息)的流量定向到另一台服务器。典型的 SRV 记录如下所示:

1
_service._protocol.example.com  SRV     10      0       5060    service.example.com

下面分别解释 SRV 记录中的元素:

  • 服务:服务名称必须以下划线(_)开头,随后紧跟句点(.)。该服务可能类似于_xmpp。
  • 协议:协议的名称必须以下划线(_)开头,随后紧跟句点(.)。该协议可能类似于_tcp。
  • :将接收此服务的原始流量的域名称。
  • 优先级:第一个数字(上例中为 10)允许您设置目标服务器的优先级。您可以使用不同的优先级设置不同的目标,这令您可以拥有该服务的备用服务器(或多个服务器)。较低的数字具有较高的优先级。
  • 权重:如果两个记录具有相同的优先级,则需要对比权重。
  • 端口:运行服务的 TCP 或 UDP 端口。
  • 目标:目标域或目标子域。此域必须具有解析为 IP 地址的 A 或 AAAA 记录。

OPT

选项资源记录。可将一个 OPT 资源记录添加到 DNS 请求或响应的附加数据部分。OPT 资源记录属于特定传输层消息(例如,UDP),不属于实际 DNS 数据。每条消息只允许具有一个 OPT 资源记录,但不是必需选项。

这是一个 伪DNS记录类型以支持 EDNS。EDNS:扩展DNS机制EDNS(Extension Mechanisms for DNS)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
control # 控制面板
winver # 检查Windows版本
wmimgmt.msc # 打开windows管理体系结构(WMI)
wscript # windows脚本宿主设置
write #写字板
wiaacmgr # 扫描仪和照相机向导
msconfig # 系统配置实用程序
mspaint # 画图板
mstsc # 远程桌面连接
magnify # 放大镜实用程序
mmc # 打开控制台
mobsync # 同步命令
dxdiag # 检查DirectX信息
devmgmt # 设备管理器
diskmgmt # 磁盘管理实用程序
dcomcnfg # 打开系统组件服务
dvdplay # DVD播放器
notepad # 打开记事本
nslookup # 网络管理的工具向导
ntbackup # 系统备份和还原
netstat -an # (TC)命令检查接口
sigverif # 文件签名验证程序
services.msc # 本地服务设置
sfc.exe # 系统文件检查器
taskmgr # 任务管理器
eventvwr # 事件查看器
eudcedit # 造字程序
explorer # 打开资源管理器
perfmon.msc # 计算机性能监测程序
regedit.exe # 注册表
rsop.msc # 组策略结果集
regedt32 # 注册表编辑器
chkdsk.exe # Chkdsk磁盘检查
certmgr.msc # 证书管理实用程序
calc # 启动计算器
charmap # 启动字符映射表
cliconfg # SQL SERVER 客户端网络实用程序
compmgmt.msc # 计算机管理
cleanmgr # 垃圾整理
osk # 打开屏幕键盘
odbcad32 # ODBC数据源管理器
lusrmgr.msc # 本机用户和组
logoff # 注销命令
iexpress # 木马捆绑工具,系统自带
Nslookup # IP地址侦测器
fsmgmt.msc # 共享文件夹管理器
utilman # 辅助工具管理器
gpedit.msc # 组策略

wscui.cpl # 安全和维护
inetcpl.cpl # Internet选项
timedate.cpl # 日期和时间
sysdm.cpl # 系统属性
bthprops.cpl #(Bluetooth Control Panel Applet. 蓝牙控制面板程序,没有安装蓝牙,不能打开)
appwiz.cpl # 程序和功能
main.cpl # 鼠标 属性
desk.cpl # 显示 设置
intl.cpl # 区域
telephon.cpl # 区域位置信息
mmsys.cpl # 声音
joy.cpl # 游戏控制器
powercfg.cpl # 电源选项
TabletPC.cpl # 笔和触摸(台式机不可用)
hdwwiz.cpl # 设备管理器
Firewall.cpl # Windows防火墙
irprops.cpl # 红外线
ncpa.cpl # 网络连接

RSA,DSA,ECDSA,EdDSA和Ed25519都用于数字签名,但只有RSA也可以用于加密。

ssh key的类型有四种,分别是 dsa、rsa、 ecdsa、ed25519,优先选择ed25519。

RSA

RSA(Rivest–Shamir–Adleman)是最早的公钥密码系统之一,被广泛用于安全数据传输。它的安全性取决于整数分解,因此永远不需要安全的RNG(随机数生成器)。与DSA相比,RSA的签名验证速度更快,但生成速度较慢。

DH算法

Diffie-Hellman 密钥协议算法是一种确保共享密钥KEY安全穿越不安全网络的方法,它是OAKLEY的一个组成部分,由Whitefield与Martin Hellman在1976年提出。这个机制的巧妙在于需要安全通信的双方可以用这个方法确定对称密钥。然后可以用这个密钥进行加密和解密。但是注意,这个密钥交换协议/算法只能用于密钥的交换,而不能进行消息的加密和解密。双方确定要用的密钥后,要使用其他对称密钥操作加密算法实际加密和解密消息。

DSA数字签名

DSA(Digital Signature Algorithm,数字签名算法,用作数字签名标准的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。它也可用于由第三方去确定签名和所签数据的真实性。DSA算法的安全性基于解离散对数的困难性,这类签字标准具有较大的兼容性和适用性,成为网络安全体系的基本构件之一。

DSA 一般用于数字签名和认证。在DSA数字签名和认证中,发送者使用自己的私钥对文件或消息进行签名,接受者收到消息后使用发送者的公钥来验证签名的真实性。DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,它比RSA要快很多。

ECC 椭圆曲线加密算法

椭圆曲线加密算法,简称ECC,是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全,RSA加密算法也是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用。据研究,160位ECC加密安全性相当于1024位RSA加密,210位ECC加密安全性相当于2048位RSA加密(有待考证)。

ECDH

ECDH全称是椭圆曲线迪菲-赫尔曼秘钥交换(Elliptic Curve Diffie–Hellman key Exchange),主要是用来在一个不安全的通道中建立起安全的共有加密资料,一般来说交换的都是私钥,这个密钥一般作为“对称加密”的密钥而被双方在后续数据传输中使用。

ECDSA

椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线密码(ECC)对数字签名算法(DSA)的模拟。ECDSA于1999年成为ANSI标准,并于2000年成为IEEE和NIST标准。它在1998年既已为ISO所接受,并且包含它的其他一些标准亦在ISO的考虑之中。与普通的离散对数问题(discrete logarithm problem DLP)和大数分解问题(integer factorization problem IFP)不同,椭圆曲线离散对数问题(elliptic curve discrete logarithm problem ECDLP)没有亚指数时间的解决方法。因此椭圆曲线密码的单位比特强度要高于其他公钥体制。

ECDSA是ECC与DSA的结合,整个签名过程与DSA类似,所不一样的是签名中采取的算法为ECC,最后签名出来的值也是分为r,s。

用于生成密钥的曲线(curve):

  • NISTP-256 curve
  • NISTP-384 curve
  • NISTP-521 curve

EdDSA

EdDSA(爱德华兹曲线数字签名算法)是一种使用基于扭曲爱德华兹曲线的Schnorr签名变体的数字签名方案。签名创建在EdDSA中是确定性的,其安全性是基于某些离散对数问题的难处理性,因此它比DSA和ECDSA更安全,后者要求每个签名都具有高质量的随机性。

Ed25519是EdDSA签名方案,但使用 SHA-512/256Curve25519;它是一条安全的椭圆形曲线,比DSA,ECDSA和EdDSA 提供更好的安全性,并且具有更好的性能。

参考:

DH算法为什么属于非对称加密算法?

RSA,DSA,ECDSA,EdDSA和Ed25519的区别

报错详情

1
2
3
4
5
6
7
8
9
PS E:\code> hexo server
hexo : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\hexo.ps1,
因为在此系统上禁止运行脚本。有关详细信息,请参阅
https:/go.microsoft.com/fwlink/?LinkID=135170 中的about_Execution_Policies。
所在位置 行:1 字符: 1
+ hexo new "PowerShell:因为在此系统上禁止运行脚本,解决方法"
+
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess

计算机上启动 Windows PowerShell 时,执行策略很可能是 Restricted(默认设置)。

  • Restricted 执行策略不允许任何脚本运行。  
  • AllSignedRemoteSigned 执行策略可防止 Windows PowerShell 运行没有数字签名的脚本。

计算机上的现用执行策略,打开 PowerShell 然后输入 :get-executionpolicy

1
2
PS C:\WINDOWS\system32> get-executionpolicy
Restricted

设置

以管理员身份打开 PowerShell 输入 set-executionpolicy remotesigned,并输入Y。

1
2
3
4
5
6
7
8
PS C:\WINDOWS\system32> set-executionpolicy remotesigned

执行策略更改
执行策略可帮助你防止执行不信任的脚本。更改执行策略可能会产生安全风险,如 https:/go.microsoft.com/fwlink/?LinkID=135170
中的 about_Execution_Policies 帮助主题所述。是否要更改执行策略?
[Y] 是(Y) [A] 全是(A) [N] 否(N) [L] 全否(L) [S] 暂停(S) [?] 帮助 (默认值为“N”): y
PS C:\WINDOWS\system32> get-executionpolicy
RemoteSigned

参考:

PowerShell:因为在此系统上禁止运行脚本,解决方法

安装npm 包:

1
npm install hexo-symbols-count-time

在博客根目录修改:_config.yml

1
2
3
4
5
6
7
8
9
symbols_count_time:
symbols: true
time: true
total_symbols: true
total_time: true
exclude_codeblock: false
awl: 4
wpm: 275
suffix: "mins."

在 Next 配置文件中 \source\_data\next.ymlconfig
(默认会添加,切记不能重复添加)

1
2
3
4
5
6
# Post wordcount display settings
# Dependencies: https://github.com/theme-next/hexo-symbols-count-time
symbols_count_time:
separated_meta: true
item_text_post: true
item_text_total: false

重新启动:

1
npx hexo s

参考:

Hexo博客NexT主题下添加字数统计和阅读时长

https://github.com/theme-next/hexo-symbols-count-time

NPX 命令方式

npm 从5.2版开始,增加了 npx 命令。npx 想要解决的主要问题,就是调用项目内部安装的模块。

使用不同的 Node.js 版本运行代码
使用 @ 指定版本,并将其与 node npm 软件包 结合使用:

1
2
npx node@10 -v #v10.18.1
npx node@12 -v #v12.14.1

这有助于避免使用 nvm 之类的工具或其他 Node.js 版本管理工具。

安装配置

重要:

安装前首先要卸载已安装的任何版本的 NodeJS,安装过程需要设置 NVM 的安装路径和 NodeJS 的快捷方式路径,可以选择任意路径。

nvm下载地址:https://github.com/coreybutler/nvm-windows/releases

在安装目录下配置:C:\Users\Administrator\AppData\Roaming\nvm

输入以下命令设置nodejs路径(相当于setting.txt中的path:):

1
2
nvm node_mirror https://npm.taobao.org/mirrors/node/
nvm npm_mirror https://npm.taobao.org/mirrors/npm/

settings.txt 文件内容:

1
2
3
4
5
6
7
root: C:\Users\Administrator\AppData\Roaming\nvm
arch: 64
proxy: none
originalpath: .
originalversion:
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

命令

重要:

通过 nvm 命令安装NodeJS时,需要以管理员权限启动命令行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 查看已经安装的版本
nvm list

# 查看已经安装的版本
nvm list installed

# 查看网络可以安装的版本
nvm list available

# 查看当前系统的位数和当前nodejs的位数
nvm arch

# 安装制定版本的node 并且可以指定平台 version 版本号 arch 平台
nvm install [arch]

nvm on # 打开nodejs版本控制
nvm off # 关闭nodejs版本控制
nvm proxy [url] # 查看和设置代理

# 设置或者查看setting.txt中的node_mirror,
# 如果不设置的默认是 https://nodejs.org/dist/
nvm node_mirror [url]

# 设置或者查看setting.txt中的npm_mirror,
# 如果不设置的话默认的是:https://github.com/npm/npm/archive/.
nvm npm_mirror [url]

nvm uninstall # 卸载制定的版本
nvm use [version] [arch] # 切换制定的node版本和位数
nvm root [path] # 设置和查看root路径
nvm version # 查看当前的版本

参考:

nvm的下载,安装与使用

1
2
3
4
5
6
7
8
9
10
11
12
# 安装模块到项目目录下,将依赖写入到dependencies中
npm install moduleName

# -save 将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。
npm install -save moduleName

# -g 将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置。
npm install -g moduleName

# -save-dev 将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖。
# -dev 主要是安装 开发用的库
npm install -save-dev moduleName

参考:

NPM install -save 和 -save-dev 傻傻分不清

对应关系:

https://github.com/sass/node-sass

NodeJS Supported node-sass version Node Module
Node 16 6.0+ 93
Node 15 5.0+ 88
Node 14 4.14+ 83
Node 13 4.13+, <5.0 79
Node 12 4.12+ 72
Node 11 4.10+, <5.0 67
Node 10 4.9+, <6.0 64
Node 8 4.5.3+, <5.0 57
Node <8 <5.0 <57
1
2
3
4
5
# 卸载
npm uninstall node-sass

# 安装
npm install node-sass@4.12 --save-dev

调用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
/// 导出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnOutPut_Click(object sender, EventArgs e)
{
try
{
ExportToExcel("候选人信息", true, "", PrintingSystem_XlSheetCreated, gctlGroup, gctlGroup1, gctlGroup2, gctlGroup3);
}
catch (Exception ex)
{
LoadingHelper.CloseForm();
XtraMessageBox.Show("获取异常:" + ex.ToString());
}
finally { LoadingHelper.CloseForm(); }
}
方法定义:

ExportToExcel方法定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/// <summary>
/// </summary>
/// DevExpress控件通用导出Excel,支持多个控件同时导出在同一个Sheet表或者分不同工作薄
/// eg:ExportToXlsx("test",true,"控件",gridControl1,gridControl2);
/// 将gridControl1和gridControl2的数据一同导出到同一个文件不同的工作薄
/// eg:ExportToXlsx("test",false,"",gridControl1,gridControl2);
/// 将gridControl1和gridControl2的数据一同导出到同一个文件同一个的工作薄
/// <param name="title">文件名</param>
/// <param name="isPageForEachLink">多个打印控件是否分多个工作薄显示</param>
/// <param name="sheetName">工作薄名称</param>
/// <param name="handler">修改sheet事件名</param>
/// <param name="printables">控件集 eg:GridControl,PivotGridControl,TreeList,ChartControl...</param>
public static void ExportToExcel(string title, bool isPageForEachLink, string sheetName, XlSheetCreatedEventHandler handler, params DevExpress.XtraPrinting.IPrintable[] printables)
{
SaveFileDialog saveFileDialog = new SaveFileDialog() { FileName = title, Title = "导出Excel", Filter = "Excel文件(*.xlsx)|*.xlsx|Excel文件(*.xls)|*.xls" };
DialogResult dialogResult = saveFileDialog.ShowDialog();
if (dialogResult == DialogResult.Cancel) return;
string fileName = saveFileDialog.FileName;
DevExpress.XtraPrintingLinks.CompositeLink link = new DevExpress.XtraPrintingLinks.CompositeLink(new DevExpress.XtraPrinting.PrintingSystem());
foreach (var item in printables)
{
var plink = new DevExpress.XtraPrinting.PrintableComponentLink() { Component = item };
link.Links.Add(plink);
}

if (handler != null)
{
// sheet 重命名
link.PrintingSystem.XlSheetCreated += handler;
}

if (isPageForEachLink)
{
//用于每个Link生成一个Sheet,不使用此方法,则合并在一个Sheet内
link.CreatePageForEachLink();
}
if (string.IsNullOrEmpty(sheetName))
sheetName = "Sheet";//默认工作薄名称
try
{
int count = 1;
//在重复名称后加(序号)
while (System.IO.File.Exists(fileName))
{
if (fileName.Contains(")."))
{
int start = fileName.LastIndexOf("(", StringComparison.Ordinal);
int end = fileName.LastIndexOf(").", StringComparison.Ordinal) - fileName.LastIndexOf("(", StringComparison.Ordinal) + 2;
fileName = fileName.Replace(fileName.Substring(start, end), $"({count}).");
}
else
{
fileName = fileName.Replace(".", $"({count}).");
}
count++;
}

if (fileName.LastIndexOf(".xlsx", StringComparison.Ordinal) >= fileName.Length - 5)
{
DevExpress.XtraPrinting.XlsxExportOptions options = new DevExpress.XtraPrinting.XlsxExportOptions()
{ SheetName = sheetName };
if (isPageForEachLink)
options.ExportMode = DevExpress.XtraPrinting.XlsxExportMode.SingleFilePageByPage;
link.ExportToXlsx(fileName, options);
}
else
{
DevExpress.XtraPrinting.XlsExportOptions options = new DevExpress.XtraPrinting.XlsExportOptions()
{ SheetName = sheetName };
if (isPageForEachLink) //15.Xls没有这个属性,15.2未知
options.ExportMode = DevExpress.XtraPrinting.XlsExportMode.SingleFilePageByPage;
link.ExportToXls(fileName, options);
}

if (DevExpress.XtraEditors.XtraMessageBox.Show("保存成功,是否打开文件?", "提示", MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.Yes)
System.Diagnostics.Process.Start(fileName); //打开指定路径下的文件
}
catch (Exception ex)
{
DevExpress.XtraEditors.XtraMessageBox.Show(ex.Message);
}
}

private static void PrintingSystem_XlSheetCreated(object sender, XlSheetCreatedEventArgs e)
{
if (e.Index == 0)
e.SheetName = "基本信息";
else if (e.Index == 1)
e.SheetName = "学业信息";
else if (e.Index == 2)
e.SheetName = "工作经历";
else if (e.Index == 3)
e.SheetName = "家庭成员";
}

参考:

How to set the sheet names for links

报错代码:

1
2
3
string repStr = "*$a2$*";
string data = "阿阿阿阿阿柔顺发膜\r";
wh.doc.Range.Replace(repStr, data, false, false);

报错:

1
The replace string cannot contain special or break characters.

替换为:

1
2
3
WordHelper wh = new WordHelper(templateFile);
ReplaceHelper helper = new ReplaceHelper(wh.doc);
helper.Replace(repStr, data);
ReplaceHelper:

ReplaceHelper帮助类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
public class ReplaceHelper
{
public ReplaceHelper(Document doc)
{
mDoc = doc;
}

/// <summary>
/// Replaces old text with new. New text can contain any special characters.
/// Old text cannot contain special charactes.
/// </summary>
/// <param name="oldText"></param>
/// <param name="newText"></param>
public void Replace(string oldText, string newText)
{
mDoc.Range.Replace(new Regex(Regex.Escape(oldText)), new ReplaceEvaluatorFindAndInsertText(newText), false);
}

public class ReplaceEvaluatorFindAndInsertText : IReplacingCallback
{
public ReplaceEvaluatorFindAndInsertText(string text)

{
mText = text;
}

/// <summary>
/// This method is called by the Aspose.Words find and replace engine for each match.
/// This method replaces the match string, even if it spans multiple runs.</summary>
/// <param name="e"></param>
/// <returns></returns>
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
{
// This is a Run node that contains either the beginning or the complete match.
Node currentNode = e.MatchNode;

// The first (and may be the only) run can contain text before the match,
// in this case it is necessary to split the run.

if (e.MatchOffset > 0)
currentNode = SplitRun((Run)currentNode, e.MatchOffset);

// This array is used to store all nodes of the match for further removing.
ArrayList runs = new ArrayList();

// Find all runs that contain parts of the match string.
int remainingLength = e.Match.Value.Length;

while ((remainingLength > 0) && (currentNode != null) && (currentNode.GetText().Length <= remainingLength))
{
runs.Add(currentNode);

remainingLength = remainingLength - currentNode.GetText().Length;

// Select the next Run node.
// Have to loop because there could be other nodes such as BookmarkStart etc.
do
{
currentNode = currentNode.NextSibling;
}
while ((currentNode != null) && (currentNode.NodeType != NodeType.Run));
}

// Split the last run that contains the match if there is any text left.
if ((currentNode != null) && (remainingLength > 0))
{
SplitRun((Run)currentNode, remainingLength);

runs.Add(currentNode);
}

// Create Document Buidler and insert text.
DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document as Document);

builder.MoveTo((Run)runs[runs.Count - 1]);

builder.Write(mText);

// Now remove all runs in the sequence.
foreach (Run run in runs)

run.Remove();

// Signal to the replace engine to do nothing because we have already done all what we wanted.
return ReplaceAction.Skip;
}

/// <summary>
/// Splits text of the specified run into two runs.
/// Inserts the new run just after the specified run.</summary>
/// <param name="run"></param>
/// <param name="position"></param>
/// <returns></returns>
private static Run SplitRun(Run run, int position)
{
Run afterRun = (Run)run.Clone(true);

afterRun.Text = run.Text.Substring(position);

run.Text = run.Text.Substring(0, position);

run.ParentNode.InsertAfter(afterRun, run);

return afterRun;
}

private string mText;
}

private Document mDoc;
}

添加环境变量

我的电脑->属性->高级->环境变量
选择PATH,在其后面添加: mysql 安装文件下面的bin文件夹
(如: D:\mysql-5.7.40-winx64\bin )(注意不要删除其他的东西)

4.新建 my.ini 文件
5.编辑my.ini文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[client]
# 设置mysql客户端默认字符集
default-character-set=utf8

[mysqld]
# 设置3306端口
port=3306
character_set_server=utf8
# 解压目录
basedir=D:\mysql-5.7.40-winx64\
# 解压目录下data目录
datadir=D:\mysql-5.7.40-winx64\data\
default-storage-engine=INNODB

#skip-grant-tables

#basedir表示mysql安装路径
#datadir表示mysql数据文件存储路径
#port表示mysql端口
#skip-grant-tables表示忽略密码

6.启动管理员模式下的 CMD,并将路径切换至 mysql 下的 bin 目录,然后输入

1
2
3
4
mysqld –install

# 移除mysql
# mysqld –remove

7.再输入 mysqld --initialize 初始化数据文件

8.输入 net start mysql 启动mysql服务

注意:data文件必须存在

9.然后再次启动 mysql 然后用命令 mysql –u root –p 进入mysql管理界面(密码可为空)

10.进入界面后更改root密码

1
2
3
4
5
6
7
8
9
10
11
# 需要先刷新
flush privileges;

ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';

# 或者
update mysql.user set authentication_string=password('123456') where user='root' and Host = 'localhost';

create user 'test'@'%' identified by '1Pon%$6';

GRANT SELECT,INSERT,CREATE ON healthcheck.* TO 'test'@'%' WITH GRANT OPTION;

123456 为新密码。

最后输入 flush privileges; 刷新权限

11.修改 my.ini 文件删除最后一句 skip-grant-tables

12.重启mysql即可正常使用

1
2
net stop mysql 
net start mysql

参考:

windows下安装MySQL5.7.34