进行网络运维,必须对网络拓扑情况进行详细的掌握,但是网络改动后,更新网络拓扑比较繁琐,维护人员容易懈怠,久而久之,通过人工绘制的网络拓扑很容易与现有网络出现偏差。

现在,可以通过python 丰富的库,结合CDP邻居信息,自动绘制网络拓扑信息,以下是实现思路:

1、登录设备,获取邻居信息;

  工具:python(telnetlib、paramiko、netmiko库)

2、筛选需要的信息,设备本地IP,本地名称,本地接口,对端设备名称,对端接口,对端IP

  工具:python(textfsm、json库)

3、根据获取进行进行画图

  工具:python(N2G库)

  文档说明:https://n2g.readthedocs.io/en/latest/diagram_plugins/DrawIo%20Module.html

4、调整图形。

一、通过python登录交换机设备的案例很多,在此不再赘述,各位可以在网上找到通过telnet、ssh的方式登录交换机,根据实际情况进行调整;这里后续通过telnet方式登录设备,输入show cdp nei detali 获取信息。

二、邻居信息处理

  2.1获取邻居信息

    输入命令后,获取交换机邻居信息如下:


 1 QIA.JSJZX.JKS>show cdp nei
2 -------------------------
3 Device ID: qia.b3.net.test.sw01
4 Entry address(es):
5 IP address: 192.17.190.225
6 Platform: cisco WS-C2960X-24TS-L, Capabilities: Switch IGMP
7 Interface: GigabitEthernet1/0/24, Port ID (outgoing port): GigabitEthernet1/0/23
8 Holdtime : 126 sec
9
10 Version :
11 Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.2(2)E6, RELEASE SOFTWARE (fc1)
12 Technical Support: http://www.cisco.com/techsupport
13 Copyright (c) 1986-2016 by Cisco Systems, Inc.
14 Compiled Fri 16-Dec-16 21:27 by prod_rel_team
15
16 advertisement version: 2
17 Protocol Hello: OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF000000000000F87B20311580FF0000
18 VTP Management Domain: ''
19 Native VLAN: 1
20 Duplex: full
21 Power Available TLV:
22
23 Power request id: 0, Power management id: 1, Power available: 0, Power management level: -1
24 Management address(es):
25 IP address: 192.17.190.225
26
27 -------------------------
28 Device ID: qia.b3.net.test.sw03
29 Entry address(es):
30 IP address: 192.17.191.132
31 Platform: cisco WS-C2960S-48TD-L, Capabilities: Switch IGMP
32 Interface: GigabitEthernet1/0/23, Port ID (outgoing port): GigabitEthernet1/0/48
33 Holdtime : 134 sec
34
35 Version :
36 Cisco IOS Software, C2960S Software (C2960S-UNIVERSALK9-M), Version 12.2(55)SE7, RELEASE SOFTWARE (fc1)
37 Technical Support: http://www.cisco.com/techsupport
38 Copyright (c) 1986-2013 by Cisco Systems, Inc.
39 Compiled Mon 28-Jan-13 10:28 by prod_rel_team
40
41 advertisement version: 2
42 Protocol Hello: OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF000000000000B000B4865F80FF0000
43 VTP Management Domain: 'default'
44 Native VLAN: 1
45 Duplex: full
46 Power Available TLV:
47
48 Power request id: 0, Power management id: 1, Power available: 0, Power management level: -1
49 Management address(es):
50 IP address: 192.19.191.132

上述为邻居信息字段,标红部分为需要提取的信息内容,下面通过textfsm工具进行提取,获取到信息内容分别为:本机名称,邻居主机名称、邻居主机IP、本机接口、邻居接口;以下是自定义的textfsm模板,文件保存为cisco_tfm.template。

 1 Value Local_hostname (\S+)
2 Value Key Local_port (\S+)
3 Value Device_name (\S+)
4 Value Device_module (\S+)
5 Value Device_IP (\S+)
6 Value Required Device_port (\S+)
7
8
9 Start
10 ^${Local_hostname}>
11 ^Device ID: ${Device_name}
12 ^\s+IP\saddress: ${Device_IP}
13 ^Platform: cisco ${Device_module},
14 ^Interface: ${Local_port},\s+Port\sID\s\(outgoing\sport\):\s${Device_port} -> Record

代码实现:

 1 import textfsm
2
3
4 #cisco :show cdp nei detail
5 data = """
6 QIA.JSJZX.JKS>show cdp nei
7 -------------------------
8 Device ID: qia.b3.net.test.sw01
9 Entry address(es):
10 IP address: 192.17.190.225
11 Platform: cisco WS-C2960X-24TS-L, Capabilities: Switch IGMP
12 Interface: GigabitEthernet1/0/24, Port ID (outgoing port): GigabitEthernet1/0/23
13 Holdtime : 126 sec
14
15 Version :
16 Cisco IOS Software, C2960X Software (C2960X-UNIVERSALK9-M), Version 15.2(2)E6, RELEASE SOFTWARE (fc1)
17 Technical Support: http://www.cisco.com/techsupport
18 Copyright (c) 1986-2016 by Cisco Systems, Inc.
19 Compiled Fri 16-Dec-16 21:27 by prod_rel_team
20
21 advertisement version: 2
22 Protocol Hello: OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF000000000000F87B20311580FF0000
23 VTP Management Domain: ''
24 Native VLAN: 1
25 Duplex: full
26 Power Available TLV:
27
28 Power request id: 0, Power management id: 1, Power available: 0, Power management level: -1
29 Management address(es):
30 IP address: 192.17.190.225
31
32 -------------------------
33 Device ID: qia.b3.net.test.sw03
34 Entry address(es):
35 IP address: 192.17.191.132
36 Platform: cisco WS-C2960S-48TD-L, Capabilities: Switch IGMP
37 Interface: GigabitEthernet1/0/23, Port ID (outgoing port): GigabitEthernet1/0/48
38 Holdtime : 134 sec
39
40 Version :
41 Cisco IOS Software, C2960S Software (C2960S-UNIVERSALK9-M), Version 12.2(55)SE7, RELEASE SOFTWARE (fc1)
42 Technical Support: http://www.cisco.com/techsupport
43 Copyright (c) 1986-2013 by Cisco Systems, Inc.
44 Compiled Mon 28-Jan-13 10:28 by prod_rel_team
45
46 advertisement version: 2
47 Protocol Hello: OUI=0x00000C, Protocol ID=0x0112; payload len=27, value=00000000FFFFFFFF010221FF000000000000B000B4865F80FF0000
48 VTP Management Domain: 'default'
49 Native VLAN: 1
50 Duplex: full
51 Power Available TLV:
52
53 Power request id: 0, Power management id: 1, Power available: 0, Power management level: -1
54 Management address(es):
55 IP address: 192.17.191.132
56 """
57
58 template_file = ".\cisco_tfm.template"
59
60 with open(template_file) as template:
61 fsm = textfsm.TextFSM(template)
62 result = fsm.ParseText(data)
63 # print(fsm.header)
64 print(result)
65 # print(len(result))

输出内容:

['Local_hostname', 'Local_port', 'Device_name', 'Device_module', 'Device_IP', 'Device_port']
[['QIA.JSJZX.JKS', 'GigabitEthernet1/0/24', 'qia.b3.net.test.sw01', 'WS-C2960X-24TS-L', '192.17.190.225', 'GigabitEthernet1/0/23'],
['', 'GigabitEthernet1/0/23', 'qia.b3.net.test.sw03', 'WS-C2960S-48TD-L', '192.17.191.132', 'GigabitEthernet1/0/48']]

注意:以上内容中,本地主机名仅在第一个邻居信息表中显示,所以需要当前设备邻居进行数据进行格式化,因此就需要用到json库。

2.2 邻居信息数据格式化

通过数据格式转换,可以得到当前主机IP、主机名称、主机接口;邻居IP、邻居名称、邻居接口信息;

代码实现:

 1 import json
2
3 ip_address = '192.168.1.1'
4 # hostname = 'zh_cisco_2960'
5
6 cdp_data = [
7 ['9QI.JSJZX.JKS', 'GigabitEthernet1/0/24', '9qi.b3.net.test.sw01', 'WS-C2960X-24TS-L', '172.17.190.225', 'GigabitEthernet1/0/23'],
8 ['', 'GigabitEthernet1/0/23', '9qi.b3.net.test.sw03', 'WS-C2960S-48TD-L', '172.17.191.132', 'GigabitEthernet1/0/48']
9 ]
10
11 def data_format(ip_address,cdp_data):
12
13 hostname = cdp_data[0][0]#二层列表格式,获取主机名
14 result_data = {
15 ip_address: {
16 hostname: {item[1]: item[2:] for item in cdp_data}
17 }
18 }
19 json_data = json.dumps(result_data, indent=2)
20
21 return json_data
22 # return the JSON formatted string
23
24 if __name__ == "__main__":
25 json_data1 = data_format(ip_address,cdp_data)
26 print(json_data1)

Json_CDPInfo

输出信息:

 1 {
2 "192.168.1.1": {#当前设备IP
3 "QI.JSJZX.JKS": {#当前设备名称
4 "GigabitEthernet1/0/24": [#本地接口,
5 "qia.b3.net.test.sw01",#邻居信息
6 "WS-C2960X-24TS-L",
7 "192.17.190.225",
8 "GigabitEthernet1/0/23"
9 ],
10 "GigabitEthernet1/0/23": [
11 "qia.b3.net.test.sw03",
12 "WS-C2960S-48TD-L",
13 "192.17.191.132",
14 "GigabitEthernet1/0/48"
15 ]
16 }
17 }
18 }

格式化以上邻居数据后,便于后续对数据进行遍历,在第三步进行读取数据进行增加节点。

遍历数据:

 1 import json
2
3 # 读取 JSON 数据
4 json_data = '''
5 {
6 "192.168.1.1": {
7 "QIA.JSJZX.JKS": {
8 "GigabitEthernet1/0/24": [
9 "qia.b3.net.test.sw01",
10 "WS-C2960X-24TS-L",
11 "192.17.190.225",
12 "GigabitEthernet1/0/23"
13 ],
14 "GigabitEthernet1/0/23": [
15 "qia.b3.net.test.sw03",
16 "WS-C2960S-48TD-L",
17 "192.17.191.132",
18 "GigabitEthernet1/0/48"
19 ]
20 }
21 }
22 }
23
24 '''
25
26 # 解析 JSON 数据
27 parsed_data = json.loads(json_data)
28
29 # 遍历数据
30 for ip_address, inner_data in parsed_data.items():
31 print(f"IP Address: {ip_address}")# 获取主机IP地址
32 # print(f"host: {inner_data}")
33
34 for hostname, cdp_data in inner_data.items():
35 print(f"Hostname: {hostname}") #获取主机名称
36 # print(type(cdp_data))
37
38 for key, values in cdp_data.items():
39 print(values)

这里在每个节点获取到邻居信息,就可以根据信息,在拓扑图中增加节点信息了。

三、进行画图、

3.1 小试牛刀

网络拓扑图中, 最重要的信息就是节点和互联线路,其他都为辅助信息

在官方文档中,已经有详细的说明可以增加节点(addnode)、增加连线(addlink);在这个两个功能中,还有其他的选项,可以补充增加,官方提供的方法,可以通过help 查看文档说明help(N2G.plugins.diagrams.N2G_DrawIO.drawio_diagram)

这里只需要重点查看Quick start部分增加节点和连接就可以了。

1 from N2G import drawio_diagram
2
3 diagram = drawio_diagram()#
4 diagram.add_diagram("Page-1")
5 diagram.add_node(id="R1")#增加节点
6 diagram.add_node(id="R2")#增加节点
7 diagram.add_link("R1", "R2", label="DF", src_label="Gi1/1", trgt_label="GE23")#增加节点之间的连线,标签名称,src_lable和trgt_lable 可以用来标注端口
8 diagram.layout(algo="kk")#图层,不重要
9 diagram.dump_file(filename="Sample_graph.drawio", folder="./Output/")#保存拓扑图

以上示例是官方最简单的画图程序,自己可以多增加几个节点进行练习。

但是在网络情况里,对每个邻居节点都登录检测检查邻居信息时,会遇到同一个连接,在两台设备上都能发现,那么创建节点和连接时会出现什么情况呢?

这里官方有说明,如果发现节点已经存在就直接跳过(也可以自定义),这样我们再写程序上就简单很多,链接里有说明。

3.2 完成程序输出

  1 from N2G import drawio_diagram
2 import textfsm
3 import json
4 import telnetlib
5 import time
6
7
8 file_path = './host_1218.txt'
9 #主机IP清单,格式如下:
10 #cisco 192.168.1.1 cisco cisco
11
12
13 template_file = "./cisco_tfm.template"
14 style_cisco = "verticalLabelPosition=bottom;html=1;verticalAlign=top;aspect=fixed;align=center;pointerEvents=1;shape=mxgraph.cisco19.rect;prIcon=l2_switch;fillColor=#FAFAFA;strokeColor=#005073;"
15 # 图标格式
16
17 def data_format(ip_address,cdp_data):
18
19 hostname = cdp_data[0][0]#二层列表格式,获取主机名
20 result_data = {
21 ip_address: {
22 hostname: {item[1]: item[2:] for item in cdp_data}
23 }
24 }
25 json_data = json.dumps(result_data, indent=2)
26
27 return json_data
28 # return the JSON formatted string
29
30
31 def cisco_telent(ip, username, password, cmd):
32 # 创建Telnet连接
33 tn = telnetlib.Telnet(ip)
34 time.sleep(0.1)
35
36 tn.read_until(b"Username:")
37 tn.write(username.encode('ascii') + b"\n")
38
39 tn.read_until(b"Password: ")
40 tn.write(password.encode('ascii') + b"\n")
41 tn.write(b"terminal length 0\n")
42
43 tn.write(cmd.encode('ascii') + b"\n")
44
45 time.sleep(0.5)
46 tn.write(b"exit\n")
47 # # 读取输出并打印
48 output = tn.read_very_eager().decode('ascii')
49
50 tn.close() # 关闭连接
51 return output
52
53
54 diagram = drawio_diagram()
55 diagram.add_diagram("Page-1")
56
57 host_info_dict = {}
58
59 node_num = 0
60 #节点计数
61 # 打开文件进行读取
62 with open(file_path, 'r') as file:
63 for line in file:
64 # 分割每一行以获取主机信息
65 host_info = line.strip().split()
66
67 # 检查是否有足够的信息
68 if len(host_info) == 4:
69 device_type, ip, username, password = host_info
70
71 # 构建设备字典
72 device = {
73 'device_type': device_type,
74 'ip': ip,
75 'username': username,
76 'password': password,
77 }
78
79 try:
80 # 执行telnet
81
82 cmd = 'show cdp neighbors detail'
83
84 command_output = cisco_telent(ip, username, password, cmd)
85 with open(template_file) as template:
86 #打开模板,进行数据提取
87 fsm = textfsm.TextFSM(template)
88 result = fsm.ParseText(command_output)
89 #列表格式数据,需要进行转换
90
91 nei_info_format = data_format(ip,result)
92 # print(nei_info_format)
93 parsed_data = json.loads(nei_info_format)
94
95 for ip_address, inner_data in parsed_data.items():
96 for local_hostname, cdp_data in inner_data.items():
97 if local_hostname not in host_info_dict:
98 #节点不存在,进行创建节点并保存节点信息
99 diagram.add_node(id=ip_address,name= local_hostname, style =style_cisco, width=60, height=60)
100 #增加本机节点
101 node_num += 1
102 # print(ip_address, local_hostname)
103 host_info_dict[local_hostname] = ip_address
104 # print(host_info_dict) 节点主机名和IP信息保存,后续进行校验节点是否已经存在
105
106 for src_label, values in cdp_data.items():
107 nei_host_name, nei_host_module, nei_host_id, trgt_label = values
108 #如果邻居节点不存在,直接创建;如果节点已经存在,则邻居ID信息要更新,更换成已经存在节点的IP地址()
109 if nei_host_name not in host_info_dict:
110 diagram.add_node(id=nei_host_id,name=nei_host_name,style=style_cisco, width=60, height=60)
111 #根据邻居信息,增加邻居节点
112 host_info_dict[nei_host_name] = nei_host_id
113 print("Add node " + nei_host_id + "secuessed.")
114 node_num += 1
115 diagram.add_link(ip_address, nei_host_id, src_label=src_label, trgt_label=trgt_label)
116 else:
117 nei_host_id = host_info_dict[nei_host_name]
118 diagram.add_link(ip_address, nei_host_id, src_label=src_label, trgt_label=trgt_label)
119 else:
120 print('节点已存在:' + local_hostname + ip_address)
121 #节点存在,检查邻居信息,根据邻居信息进行判断,是否添加邻居节点
122 for src_label, values in cdp_data.items():
123 nei_host_name, nei_host_module, nei_host_id, trgt_label = values
124 if nei_host_name not in host_info_dict:
125 diagram.add_node(id=nei_host_id, name=nei_host_name, style=style_cisco, width=60, height=60)
126 #根据邻居信息,增加邻居节点
127 host_info_dict[nei_host_name] = nei_host_id
128 print("Add node " + nei_host_id + "secuessed.")
129 node_num += 1
130 diagram.add_link(ip_address, nei_host_id, src_label=src_label, trgt_label=trgt_label)
131 else:
132 nei_host_id = host_info_dict[nei_host_name]
133 diagram.add_link(ip_address, nei_host_id, src_label=src_label, trgt_label=trgt_label)
134
135 # print("Add node " + ip_address + " sucessed.")
136
137 except Exception as e:
138 print(f"Failed to connect to {ip}: {e}")
139
140 else:
141 print(f"Invalid line in the file: {line.strip()}")
142 print(node_num)
143 print(host_info_dict,len(host_info_dict))
144 diagram.dump_file(filename="Sample_campus_00.drawio", folder="./Output/")

draw_topology_N2G

以上脚本,除路径本人修改过以外,整个程序在网络环境中进行的验证。

说明:

1、在第57行,创建了1个字典,用来保存发现的邻居数据,主机名、主机名称,用来后续对新发现节点进行判断。为什么还需要进行判断?

因为当一台设备上有多个IP地址时,与之互联的设备邻居信息显示的IP信息可能是不一样的,所以再次通过主机名再次进行判断;当然这里也不是很严谨,因为设备名称可能存在全局不唯一的情况,所以在cisco NX-OS中,CDP邻居信息会显示设备的序列号,这样就避免前面的情况。

2、因为网络规模较大,输出的拓扑文件也比较大,所以在第59行,增加了一个计数,在每增加1个节点,都进行一个保存信息,最终输出看有多少网络设备。

3、为什么add_node 方法中有非官方说明的字段“name”.

答:非标准字段,生成的拓扑图会以属性字段描述节点,鼠标放到节点上就可显示,不会直接显示出来,包括前面已经提取到的设备型号,也可以通过增加字段module在拓扑图中隐性的展示;右键成编辑节点数据,即可查看或编辑数据

四、因为在程序中没有指定每个节点的坐标位置,所以生成的拓扑图,所有的图标节点都是在默认位置,所以会出现重叠的情况,只需要在调整图形-布局,选择“垂直流“就可自动重新排列。

Cisco 交换机利用CDP数据自动绘制网络拓扑图[drawio]-实践的更多相关文章

  1. Ucinet6 + Netdraw 根据excel文件绘制网络拓扑图

    条件: 具备Ucinet6 和 Netdraw 两款软件的Windows excel文件格式(.xlsx  .xls  .csv):必须是数字,如果现有的文件不是数字,可以采用某种编码的方式将其映射成 ...

  2. 网络/运维工程师visio2013模具图标 绘制漂亮的网络拓扑图 狮子XL工程师美学思想

    visio2013狮子XL自定义运维模具下载: 链接:http://pan.baidu.com/s/1bo779Kz 密码:xh3s 狮子XL 的美学思想: 1,一次痛苦,一生幸福. 之前,在绘制网络 ...

  3. 基于网络拓扑图通过RCMS对网络进行配置

    目录 基于网络拓扑图通过RCMS对网络进行配置 一些基本命令 对网络拓扑图1的简单配置 二层交换机S3 三层交换机 S2 实验结果 对网络拓扑图2的简单配置 NAT.ACL配置公网IP 基于网络拓扑图 ...

  4. 基于HTML5的网络拓扑图(1)

    什么是网络拓扑 网络拓扑,指构成网络的成员间特定的排列方式.分为物理的,即真实的.或者逻辑的,即虚拟的两种.如果两个网络的连接结构相同,我们就説它们的网络拓扑相同,尽管它们各自内部的物理接线.节点间距 ...

  5. VBA GET POST HTTP VBA网络爬虫 最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码

    最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码 通过接口获取股票数据内容的主要优点包括以下几点: 实时性高:通过访问股票数据接口,可以实时获取到股票的实 ...

  6. 利用在线工具根据JSon数据自动生成对应的Java实体类

    如果你希望根据JSon数据自动生成对应的Java实体类,并且希望能进行变量的重命名,那么“JSON To Java”一定适合你.(下面的地址需要FQ) https://jsontojava.appsp ...

  7. [转]漫谈数据中心CLOS网络架构

    http://djt.qq.com/article/view/238 1.数据中心网络架构挑战 随着技术的发展,数据中心的规模越来越大,一个数据中心的服务器容量从几年前的几千台服务器发展到今天的几万甚 ...

  8. Cisco 交换机的操作

    Cisco的工作模式 Cisco设备有常用模式为:用户模式.特权模式.全局模式.端口模式.首先它们之间呈现出递进关系:用户模式->特权模式->全局模式->端口模式 1.用户模式 交换 ...

  9. Cisco 交换机与路由器故障处理方法分享

    一.网络的复杂性 一般网络包括路由.拨号.交换.视频.WAN(ISDN.帧中继.ATM.…).LAN.VLAN.… 二.故障处理模型 1. 界定问题(Define the Problem) 详细而精确 ...

  10. 利用 VMWare 搭建随机拓扑网络

    这篇文章是计算机网络上机实验课的作业. 实验任务:利用 VMWare 搭建一个由 5 个主机组成的随机拓扑的网络.要求该网络中至少有 2 个子网,两个路由器 .实验的网络拓扑图如下: 网络中有两个路由 ...

随机推荐

  1. numpy中矩阵的逆,求解,特征值,特征向量

    逆:numpy.linalg.inv() # 求矩阵的逆import numpy as npa=np.mat('1 0;0 1')#生成一个矩阵print(type(a))b=np.linalg.in ...

  2. Solution -「九省联考 2018」劈配

    Description Link. 一年一度的综艺节目<中国新代码>又开始了.Zayid 从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 轻车熟路的 Za ...

  3. Teamcenter RAC 开发之《新建Item》

    private TCComponentItem createOperation(String itemName,String itemType) { //obejct_name itemType tr ...

  4. How to parse OR AND within text

    假设你有一行 String condition = "A or B and C"; 语句,请问怎么做才能变成一行真正的逻辑表达式(能在计算机中运行计算)? Resolution 声 ...

  5. 深挖 Python 元组 pt.1

    哈喽大家好,我是咸鱼 好久不见甚是想念,2023 年最后一次法定节假日已经结束了,不知道各位小伙伴是不是跟咸鱼一样今天就开始"搬砖"了呢? 我们知道元组(tuple)是 Pytho ...

  6. fasthttp + `page partial gziped cache`: 页面输出服务性能提升20%

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 接上一篇:http 中使用 gzip 输出内容时,如何预先 ...

  7. Chromium Trace and Perfetto使用详解

    1. Trace chromium 在 base 库中提供了 base::trace_event::TraceLog 类,该类是 TRACE_EVENT* , TRACE_COUNTER* 等宏的底层 ...

  8. 小白也能看懂的 AUC 曲线详解

    小白也能看懂的 AUC 曲线详解 简介 上篇文章 小白也能看懂的 ROC 曲线详解 介绍了 ROC 曲线.本文介绍 AUC.AUC 的全名为Area Under the ROC Curve,即 ROC ...

  9. 脚踏esbuild祥云,胸怀tsx利刃,身披scss羽衣,追寻前端的本质

    本文所有内容,纯属个人观点,无意与任何人争论 前端技术的现状 我觉得前端技术发展到现在有两个最主要的特征 前端工具链为前端工程化提供了强有力的支持 这方面主要是webpack.rollup.esbui ...

  10. CDQ分治(初步入门)

    CDQ分治 CDQ分治,传说中是一个神犇创造的算法. 在了解这种算法之前,我们有必要了解一下一种基本的思想:分治. 分治介绍 分而治之,将原问题不断划分成若干个子问题,直到子问题规模小到足以直接解决 ...