分类 默认分类 下的文章

协议分析实验 11 OSPF

更好的阅读体验:

  1. https://www.cnblogs.com/rabbit-dayi/p/17826062.html
  2. https://blog.dayi.ink/?p=101
  3. https://type.dayiyi.top/index.php/archives/247/
  4. https://cmd.dayi.ink/1BErSmorSiK5ntFzs_Fhcw?both#Multi-Area-OSPF

任务:

① 选择样例中的OSPF2-1等6个和OSPF相关的网络拓扑,依次打开;
② 启动设备;
③ 从任意路由器端口启动wireshark,捕获报文。
④ 将其中的路由器端口shutdown,过一段时间再undo shutdown,观察OSPF报文的变化。
2、分析其中的OSPF报文。

回答下面的问题:
1、每种拓扑结构中用到了OSPF的什么功能?
2、给出协议报文截图并进行分析。

Multi-Area OSPF

开机

开始抓包

他的意思好像是随便找就行,这几个网络大差不差,我在R2上抓包的。

关机

随便找个别的,右键关机

然后抓包。

OSPF Hello报文

Open Shortest Path First
    OSPF Header
        Version: 2 # 版本2
        Message Type: Hello Packet (1) # 这是一个HELLO报文
        Packet Length: 52 # 包的长度
        Source OSPF Router: 10.0.2.2 #发送该报文的OSPF路由器的IP地址是10.0.2.2
        Area ID: 0.0.0.2 # 表示报文所属的区域ID为0.0.0.2。
        Checksum: 0xcb86 [correct] #校验和
        Auth Type: Null (0) #表示认证类型为Null,即无认证
        Auth Data (none): 0000000000000000 #认证数据为空
    OSPF Hello Packet #Hello报文的信息
        Network Mask: 255.255.255.0 #网络掩码
        Hello Interval [sec]: 10 #Hello报文的发送时延
        Options: 0x02, (E) External Routing # 外部路由
        Router Priority: 1 # 表示该路由器的优先级为1
        Router Dead Interval [sec]: 40 #表示路由器失效的时间间隔为40秒。
        Designated Router: 10.0.124.4 #指定路由器的IP地址为10.0.124.4。
        Backup Designated Router: 10.0.124.2 #备份指定路由器的IP地址为10.0.124.2
        Active Neighbor: 10.0.1.1  #表示活动邻居的IP地址是10.0.1.1
        Active Neighbor: 10.0.4.4 #表示活动邻居的IP地址是10.0.4.4

包的长度:

OSPF过程:

假设从启动开始:

  1. 路由器 A 启动:路由器 A 启动并与邻居路由器 B 形成邻接关系。
  2. 数据库描述交换:路由器 A 和 B 通过发送 Database Description 报文来交换它们的链路状态数据库概要。
  3. 路由器 A 发现信息缺失:在数据库描述交换后,路由器 A 发现它缺少路由器 B 的某个链路状态信息。发送 LS Request:路由器 A 向路由器 B 发送 LS Request,请求缺失的链路状态信息。
  4. 路由器 B 响应 LS Update:路由器 B 收到 LS Request 后,回复一个包含所请求链路状态信息的 LS Update 报文。
  5. 路由器 A 收到 LS Update 后,发送 LS Acknowledge 给路由器 B,确认已成功接收到更新信息

这里的话,两个路由器ARP报文交换之后,知道相互的IP,三层可以正常访问后开始OSPF交换信息。

R5->R1

[R5]display ip int brief 
*down: administratively down
^down: standby
(l): loopback
(s): spoofing
The number of interface that is UP in Physical is 5
The number of interface that is DOWN in Physical is 3
The number of interface that is UP in Protocol is 5
The number of interface that is DOWN in Protocol is 3

Interface                         IP Address/Mask      Physical   Protocol  
GigabitEthernet0/0/0              unassigned           down       down      
GigabitEthernet0/0/1              unassigned           down       down      
LoopBack0                         10.0.5.5/24          up         up(s)     
LoopBack1                         10.1.0.1/24          up         up(s)     
LoopBack2                         10.1.1.1/24          up         up(s)     
NULL0                             unassigned           up         up(s)     
Serial2/0/0                       10.0.35.5/24         up         up        
Serial2/0/1                       unassigned           down       down      
[R5]tracert 10.0.1.1

 traceroute to  10.0.1.1(10.0.1.1), max hops: 30 ,packet length: 40,press CTRL_C
 to break 

 1 10.0.35.3 20 ms  10 ms  10 ms 

 2 10.0.23.2 30 ms  40 ms  20 ms 

 3 10.0.124.1 20 ms  20 ms  30 ms 
[R5]

OSPF LS UPDATE 链路更新报文

好大

Open Shortest Path First
    OSPF Header #公共首部
        Version: 2 #版本号2
        Message Type: LS Update (4) #链路更新报文
        Packet Length: 64 #长度64
        Source OSPF Router: 10.0.2.2 #报文来自这个路由器
        Area ID: 0.0.0.2 #来源
        Checksum: 0x5552 [correct]
        Auth Type: Null (0) #认证
        Auth Data (none): 0000000000000000
    LS Update Packet
        Number of LSAs: 1 #LSA(链路状态报告)报文数量
        LSA-type 1 (Router-LSA), len 36
            .000 0000 0000 0001 = LS Age (seconds): 1 #LSA的年龄
            0... .... .... .... = Do Not Age Flag: 0 #无年龄FLAG
            Options: 0x02, (E) External Routing #支持外部路由
                0... .... = DN: Not set
                .0.. .... = O: Not set
                ..0. .... = (DC) Demand Circuits: Not supported
                ...0 .... = (L) LLS Data block: Not Present
                .... 0... = (N) NSSA: Not supported
                .... .0.. = (MC) Multicast: Not capable
                .... ..1. = (E) External Routing: Capable
                .... ...0 = (MT) Multi-Topology Routing: No
            LS Type: Router-LSA (1) #LSA的类型,这里是1 路由LSA
            Link State ID: 10.0.2.2 #链路状态ID
            Advertising Router: 10.0.2.2 #发布此LSA的路由器IP地址
            Sequence Number: 0x80000006 #序列号(防止过失传播)
            Checksum: 0xf321 #校验和
            Length: 36 #长度
            Flags: 0x01, (B) Area border router #标志,该路由器是边界路由
                0... .... = (H) flag: No
                ...0 .... = (N) flag: No
                .... 0... = (W) Wild-card multicast receiver: No
                .... .0.. = (V) Virtual link endpoint: No
                .... ..0. = (E) AS boundary router: No
                .... ...1 = (B) Area border router: Yes
            Number of Links: 1 #LSA包含的链路数量
            Type: Transit  ID: 10.0.124.4      Data: 10.0.124.2      Metric: 10
                Link ID: 10.0.124.4 - IP address of Designated Router 链路ID
                Link Data: 10.0.124.2 #链路数据
                Link Type: 2 - Connection to a transit network #传输网络
                Number of Metrics: 0 - TOS #度量数量
                0 Metric: 10 #度量值为10

再看一个非路由协议的LSA

Open Shortest Path First
    OSPF Header
        Version: 2
        Message Type: LS Update (4)
        Packet Length: 108
        Source OSPF Router: 10.0.4.4
        Area ID: 0.0.0.2
        Checksum: 0x95df [correct]
        Auth Type: Null (0)
        Auth Data (none): 0000000000000000
    LS Update Packet
        Number of LSAs: 2 # 这里有两个LSA
        LSA-type 1 (Router-LSA), len 48
        LSA-type 2 (Network-LSA), len 32
            .000 0000 0000 0001 = LS Age (seconds): 1 
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Network-LSA (2) # 网络路由
            Link State ID: 10.0.124.4 #链路状态ID
            Advertising Router: 10.0.4.4 #发布此LSA的路由器IP地址
            Sequence Number: 0x80000004 #序列号
            Checksum: 0x207a
            Length: 32
            Netmask: 255.255.255.0 #网络子网掩码
            Attached Router: 10.0.4.4 #附加的路由(LSA所代表的网络包含这个路由器)
            Attached Router: 10.0.2.2 #附加的路由

OSPF LS request

这个LS ID 不一定完全等于IP地址。

LS ID:

  • 特定链路状态广告(LSA)的标识符
  • 在路由器 LSA 中,它通常是发出 LSA 的路由器的接口 IP 地址;在网络 LSA 中,它是网络的 IP 地址;而在汇总和外部 LSA 中,它代表了被汇总或外部网络的 IP 地址。
  • 虽然 Link State ID 通常以 IP 地址格式出现,但它的含义和用途与实际的 IP 地址不同。

感觉好多一样的包诶


Open Shortest Path First
    OSPF Header
        Version: 2
        Message Type: LS Request (3)
        Packet Length: 168
        Source OSPF Router: 10.0.1.1
        Area ID: 0.0.0.2
        Checksum: 0x2707 [correct]
        Auth Type: Null (0)
        Auth Data (none): 0000000000000000
        
    Link State Request # 链路状态请求,表示这是一个请求特定链路状态信息的请求。
        LS Type: Router-LSA (1) # LS类型:路由器-LSA(1),表示请求的是路由器链路状态广告。
        Link State ID: 10.0.2.2 # 链路状态ID:10.0.2.2,标识特定链路状态的唯一ID。
        Advertising Router: 10.0.2.2 # 广告路由器:10.0.2.2,表示发布该链路状态信息的路由器。
        
    Link State Request
        LS Type: Router-LSA (1) #一样的
        Link State ID: 10.0.1.1 #链路状态ID
        Advertising Router: 10.0.1.1
    Link State Request
        LS Type: Router-LSA (1) #路由LSA
        Link State ID: 10.0.4.4
        Advertising Router: 10.0.4.4
    Link State Request
        LS Type: Network-LSA (2) #网络LSA
        Link State ID: 10.0.124.4 
        Advertising Router: 10.0.4.
    #汇总-LSA(IP网络)的请求,用于汇总和传播IP网络的路由信息。    
    Link State Request
        LS Type: Summary-LSA (IP network) (3)
        Link State ID: 10.0.2.0
        Advertising Router: 10.0.2.2
    【...省略一点相同类型的LSA】
    Link State Request
        LS Type: Summary-LSA (IP network) (3)
        Link State ID: 10.1.1.0
        Advertising Router: 10.0.2.2
    Link State Request
        LS Type: AS-External-LSA (ASBR) (5) # AS-外部-LSA(自治系统边界路由器),描述来自外部自治系统的路由。
        Link State ID: 0.0.0.0
        Advertising Router: 10.0.4.4

OSPF LS UPDATE

Open Shortest Path First
    OSPF Header
        Version: 2
        Message Type: LS Update (4)
        Packet Length: 412
        Source OSPF Router: 10.0.2.2
        Area ID: 0.0.0.2
        Checksum: 0xaf95 [correct]
        Auth Type: Null (0)
        Auth Data (none): 0000000000000000
    LS Update Packet
        Number of LSAs: 12 #包含12个包
        LSA-type 1 (Router-LSA), len 36 #路由LSA
            .000 0000 0000 0001 = LS Age (seconds): 1 #AGE
            0... .... .... .... = Do Not Age Flag: 0 #no age
            Options: 0x02, (E) External Routing #外部路由
            LS Type: Router-LSA (1) #LSA的更新
            Link State ID: 10.0.2.2 #LS ID
            Advertising Router: 10.0.2.2 #LS广播路由器,应该是IP地址
            Sequence Number: 0x80000007 #段序号
            Checksum: 0xf122
            Length: 36 #长度
            Flags: 0x01, (B) Area border router #区域内广播下外部路由?
            Number of Links: 1 #连接数量
            Type: Transit  ID: 10.0.124.4      Data: 10.0.124.2  #路由器接口的IP地址。    Metric: 10
        LSA-type 1 (Router-LSA), len 36
            .000 0010 1011 1010 = LS Age (seconds): 698
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Router-LSA (1)
            Link State ID: 10.0.1.1
            Advertising Router: 10.0.1.1
            Sequence Number: 0x80000006
            Checksum: 0x0b0e
            Length: 36
            Flags: 0x02, (E) AS boundary router #区域内信息进行汇总
            Number of Links: 1
            Type: Transit  ID: 10.0.124.4      Data: 10.0.124.1      Metric: 10  # Transit  ID: 10.0.124.4 也是,表示从这个地方也可以访问到10.0.124.4的网络
        LSA-type 1 (Router-LSA), len 48
            .000 0000 0000 0010 = LS Age (seconds): 2
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Router-LSA (1)
            Link State ID: 10.0.4.4
            Advertising Router: 10.0.4.4
            Sequence Number: 0x8000000a
            Checksum: 0x499e
            Length: 48
            Flags: 0x02, (E) AS boundary router
            Number of Links: 2
              Type: Transit  ID: 10.0.124.4      Data: 10.0.124.4      Metric: 10 #多个路由穿底
              Type: Stub     ID: 10.0.4.0        Data: 255.255.255.0   Metric: 0 #直连网络或主机路由
        LSA-type 2 (Network-LSA), len 32
            .000 0000 0000 0010 = LS Age (seconds): 2
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Network-LSA (2)
            Link State ID: 10.0.124.4
            Advertising Router: 10.0.4.4
            Sequence Number: 0x80000005
            Checksum: 0x1e7b
            Length: 32
            Netmask: 255.255.255.0
            Attached Router: 10.0.4.4
            Attached Router: 10.0.2.2
        LSA-type 3 (Summary-LSA (IP network)), len 28
            .000 0010 1111 0000 = LS Age (seconds): 752
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Summary-LSA (IP network) (3)
            Link State ID: 10.0.2.0
            Advertising Router: 10.0.2.2
            Sequence Number: 0x80000001
            Checksum: 0x5ee4
            Length: 28
            Netmask: 255.255.255.0
            TOS: 0
            Metric: 0
       【...省略一点相同类型的LSA】
        LSA-type 3 (Summary-LSA (IP network)), len 28
            .000 0010 1101 1110 = LS Age (seconds): 734
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Summary-LSA (IP network) (3)
            Link State ID: 10.1.0.0
            Advertising Router: 10.0.2.2
            Sequence Number: 0x80000001
            Checksum: 0x29d0
            Length: 28
            Netmask: 255.255.255.0
            TOS: 0
            Metric: 9764
        LSA-type 3 (Summary-LSA (IP network)), len 28
            .000 0010 1101 1110 = LS Age (seconds): 734
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: Summary-LSA (IP network) (3)
            Link State ID: 10.1.1.0
            Advertising Router: 10.0.2.2
            Sequence Number: 0x80000001
            Checksum: 0x1eda
            Length: 28
            Netmask: 255.255.255.0
            TOS: 0
            Metric: 9764
        LSA-type 5 (AS-External-LSA (ASBR)), len 36
            .000 0010 1110 1110 = LS Age (seconds): 750
            0... .... .... .... = Do Not Age Flag: 0
            Options: 0x02, (E) External Routing
            LS Type: AS-External-LSA (ASBR) (5)
            Link State ID: 0.0.0.0
            Advertising Router: 10.0.4.4
            Sequence Number: 0x80000001
            Checksum: 0xec52
            Length: 36
            Netmask: 0.0.0.0
            0... .... = External Type: Type 1 (metric is specified in the same units as interface cost)
            .000 0000 = TOS: 0
            Metric: 1
            Forwarding Address: 0.0.0.0
            External Route Tag: 1

OSPF ACK

这里有两个LSA


Open Shortest Path First
    OSPF Header
        Version: 2
        Message Type: LS Acknowledge (5)
        Packet Length: 64
        Source OSPF Router: 10.0.2.2
        Area ID: 0.0.0.2
        Checksum: 0xd527 [correct]
        Auth Type: Null (0)
        Auth Data (none): 0000000000000000
    LSA-type 2 (Network-LSA), len 32
        .000 0000 0000 0001 = LS Age (seconds): 1
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Network-LSA (2)
        Link State ID: 10.0.124.4
        Advertising Router: 10.0.4.4
        Sequence Number: 0x80000005
        Checksum: 0x1e7b
        Length: 32
    LSA-type 1 (Router-LSA), len 48
        .000 0000 0000 0001 = LS Age (seconds): 1
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Router-LSA (1)
        Link State ID: 10.0.4.4
        Advertising Router: 10.0.4.4
        Sequence Number: 0x8000000a
        Checksum: 0x499e
        Length: 48

OSPF DB 描述

建立邻居关系后,交换数据库概要

Open Shortest Path First
    OSPF Header
        Version: 2
        Message Type: DB Description (2)
        Packet Length: 332
        Source OSPF Router: 10.0.1.1
        Area ID: 0.0.0.2
        Checksum: 0xcece [correct]
        Auth Type: Null (0)
        Auth Data (none): 0000000000000000
    OSPF DB Description
        Interface MTU: 0
        Options: 0x02, (E) External Routing
        DB Description: 0x00
        DD Sequence: 52
    LSA-type 1 (Router-LSA), len 36
        .000 0000 0000 0001 = LS Age (seconds): 1
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Router-LSA (1)
        Link State ID: 10.0.1.1
        Advertising Router: 10.0.1.1
        Sequence Number: 0x80000007
        Checksum: 0xf425
        Length: 36
    LSA-type 1 (Router-LSA), len 36
        .000 0000 0000 0010 = LS Age (seconds): 2
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Router-LSA (1)
        Link State ID: 10.0.2.2
        Advertising Router: 10.0.2.2
        Sequence Number: 0x80000008
        Checksum: 0xef23
        Length: 36
    LSA-type 1 (Router-LSA), len 48
        .000 0000 0000 0100 = LS Age (seconds): 4
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Router-LSA (1)
        Link State ID: 10.0.4.4
        Advertising Router: 10.0.4.4
        Sequence Number: 0x8000000a
        Checksum: 0x499e
        Length: 48
    LSA-type 2 (Network-LSA), len 32
        .000 0000 0000 0100 = LS Age (seconds): 4
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Network-LSA (2)
        Link State ID: 10.0.124.4
        Advertising Router: 10.0.4.4
        Sequence Number: 0x80000005
        Checksum: 0x1e7b
        Length: 32
    LSA-type 3 (Summary-LSA (IP network)), len 28
        .000 0010 1111 0010 = LS Age (seconds): 754
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Summary-LSA (IP network) (3)
        Link State ID: 10.0.2.0
        Advertising Router: 10.0.2.2
        Sequence Number: 0x80000001
        Checksum: 0x5ee4
        Length: 28
    【...省略一点相同类型的LSA】
    LSA-type 3 (Summary-LSA (IP network)), len 28
        .000 0010 1110 0000 = LS Age (seconds): 736
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: Summary-LSA (IP network) (3)
        Link State ID: 10.1.1.0
        Advertising Router: 10.0.2.2
        Sequence Number: 0x80000001
        Checksum: 0x1eda
        Length: 28
    LSA-type 5 (AS-External-LSA (ASBR)), len 36
        .000 0010 1111 0000 = LS Age (seconds): 752
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: AS-External-LSA (ASBR) (5)
        Link State ID: 0.0.0.0
        Advertising Router: 10.0.4.4
        Sequence Number: 0x80000001
        Checksum: 0xec52
        Length: 36
    LSA-type 5 (AS-External-LSA (ASBR)), len 36
        .000 0000 0000 0101 = LS Age (seconds): 5
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: AS-External-LSA (ASBR) (5)
        Link State ID: 10.0.1.0
        Advertising Router: 10.0.1.1
        Sequence Number: 0x80000001
        Checksum: 0x0aaf
        Length: 36
    LSA-type 5 (AS-External-LSA (ASBR)), len 36
        .000 0000 0000 0101 = LS Age (seconds): 5
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: AS-External-LSA (ASBR) (5)
        Link State ID: 10.2.0.0
        Advertising Router: 10.0.1.1
        Sequence Number: 0x80000001
        Checksum: 0x02b6
        Length: 36
    LSA-type 5 (AS-External-LSA (ASBR)), len 36
        .000 0000 0000 0010 = LS Age (seconds): 2
        0... .... .... .... = Do Not Age Flag: 0
        Options: 0x02, (E) External Routing
        LS Type: AS-External-LSA (ASBR) (5)
        Link State ID: 10.0.124.0
        Advertising Router: 10.0.1.1
        Sequence Number: 0x80000001
        Checksum: 0xbb82
        Length: 36

功能

  • LS Update(链路状态更新):
    用途:LS Update 报文用于传播链路状态信息。这些报文携带链路状态广告(LSA)
  • LS Acknowledge(链路状态确认):
    用途:LS Acknowledge 报文用于确认收到 LS Update 报文。每当一个路由器接收到一个 LS Update 报文,它就会发送一个 LS Acknowledge 报文来确认收到。相当于TCP的ACK
  • LS Request(链路状态请求):
    用途:LS Request 报文用于请求更多的链路状态信息。当一个路由器需要获取特定的链路状态信息来更新其本地数据库时,它会发送 LS Request 报文。
  • Database Description (数据库描述):
    用途:Database Description (DBD) 报文用于在 OSPF 的邻接建立过程中交换路由器的链路状态数据库的概要信息。在 OSPF 邻居关系建立过程中,路由器首先通过发送 DBD 报文来描述其链路状态数据库的内容。

过程大概这样

  1. 发送 LS Request:路由器发现它的链路状态数据库缺少某些信息或某些信息已过时时,发送 LS Request 报文给邻居路由器,请求缺失的或最新的链路状态信息。
  2. 收到 LS Request 的响应:收到 LS Request 的路由器会检查其数据库,如果有被请求的信息,它会使用 LS Update 报文来响应。LS Update 报文包含了被请求的链路状态信息。
  3. 发送 LS Acknowledge:发送 LS Request 的路由器收到 LS Update 后,会发送 LS Acknowledge 报文来确认收到更新。

对于具体的信息就是LSA啦,然后LSA又分11种。

1.每种拓扑结构中用到了OSPF的什么功能

拓扑结构中使用了OSPF协议的多区域(Multi-Area)功能。在图中可以看到,有多个区域(Area0, Area1, Area2),而且每个区域内部有不同的路由器(R1, R2, R3, R4, R5)和网络。每个路由器的接口旁边有IP地址和子网掩码,以及区域标识。

OSPF将一个自治系统(AS)分割成不同的区域以减少路由表的大小和路由更新的复杂性。每个区域内部进行路由选择,而区域之间的路由选择则通过区域边界路由器(Area Border Router, ABR)来完成。

拓扑中的"LookBack"指的是用于OSPF路由器ID分配的环回(loopback)接口,这是OSPF网络设计中的一个常见做法,以确保路由器ID的稳定性。环回接口的地址不会因为物理接口的状态变化而改变,因此它为OSPF提供了一个稳定的标识。

2.给出协议报文截图并进行分析。

上面已经分析啦。

OSPF&LSA

1.每种拓扑结构中用到了OSPF的什么功能

  • 多区域 OSPF 三个不同的OSPF区域(Area 0, Area 1, 和 Area 2)。
  • 环回接口 (Loopback Interfaces): 每个路由器配置有环回接口,用于稳定的 OSPF 路由器 ID。
  • ABR(区域边界路由器): 这里由于是Area2的直接交换机连上了Area0,然后就等于直接连上了三个路由器,这样的话Area0估计要选举出来一个路由器。

2.给出协议报文截图并进行分析。

关机这三个,然后启动:

二层交换机里没东西,可以当傻瓜交换机用

在GE3上抓的包:

他们几个用了组播..

234.1

ip.addr==10.1.234.1

是它

包:

发送完HELLO报文之后交换数据库描述

3->1 DB交换
3<-1 先建立连接

这个包没数据,感觉可能是没有LSA的数据,也可能是为了先建立连接。对上号。

然后开始发概要:

然后3给1发了一大堆LSA概要:

然后1问3要LSA信息:

1跟3又来了次DB描述(不是很清楚为啥)

然后3->1 LSA信息:

然后1 往组播地址发了信息:

然后1 往组播发了一堆ACK:

DB描述交换过程

  • 1.主动方发送DB描述报文:OSPF邻居关系建立时,主动方(Master)首先发送DB描述报文给被动方(Slave)。DB描述报文中包含了主动方所知道的链路状态数据库的描述信息。
  • 2.被动方确认并发送确认号:被动方收到DB描述报文后,会确认接收到的DB描述报文,并发送一个确认号(DD Sequence Number)给主动方。确认号表示被动方期望接收到的下一个DB描述报文的序列号。
  • 3.主动方发送下一个DB描述报文:主动方收到被动方发送的确认号后,会根据确认号确定下一个需要发送的DB描述报文,并将其发送给被动方。这个过程会一直进行,直到主动方发送完所有的DB描述报文。
  • 4.被动方确认并发送确认号:被动方收到主动方发送的DB描述报文后,会确认接收到的报文,并发送下一个期望接收到的DB描述报文的确认号。
  • 重复步骤3和步骤4:主动方和被动方交替进行DB描述报文的发送和确认,直到双方的链路状态数据库的描述信息完全交换。

234.2

几乎一样

234.4

也几乎一样

组播:

  • 224.0.0.5: 所有OSPF路由器的地址,用于大多数OSPF控制和更新消息。
  • 224.0.0.6: 所有OSPF指定路由器的地址,主要用于从指定路由器(Designated Router, DR)和备份指定路由器(Backup Designated Router, BDR)到其它OSPF路由器的更新消息。

LSA

LSA-TYPE1

  • 描述路由器自身的直连链路信息(接口的地址、接口类型、接口开销打包成1类LSA通告给邻居)
  • 每个在OSPF里的路由器都会生成一个这个
  • 但,每台OSPF路由器只能产生一条类型1的LSA,即使有多个 OSPF接口,也只有一条类型 1 的 LSA
LSA-type 1 (Router-LSA), len 48
    .000 0000 0000 0001 = LS Age (seconds): 1 
    0... .... .... .... = Do Not Age Flag: 0
    Options: 0x02, (E) External Routing
    LS Type: Router-LSA (1) #类型1 路由LSA
    Link State ID: 10.0.3.3
    Advertising Router: 10.0.3.3
    Sequence Number: 0x80000011
    Checksum: 0x1cf6
    Length: 48
    Flags: 0x01, (B) Area border router
    Number of Links: 2
    Type: Transit  ID: 10.1.234.3      Data: 10.1.234.3      Metric: 1 #接口
        Link ID: 10.1.234.3 - IP address of Designated Router
        Link Data: 10.1.234.3
        Link Type: 2 - Connection to a transit network 
        Number of Metrics: 0 - TOS
        0 
        Metric: 1
    Type: Stub     ID: 10.0.3.0        Data: 255.255.255.0   Metric: 0 #连了个子网
        Link ID: 10.0.3.0 - IP network/subnet number #子网信息
        Link Data: 255.255.255.0 #掩码
        Link Type: 3 - Connection to a stub network
        Number of Metrics: 0 - TOS
        0 # 指示有多少不同类型的服务(TOS)的度量值。过时了
        Metric: 0 #成本

LSA-TYPE 2

  • 作用:描述多点可达环境中的路由器,以及掩码网段信息(描述广播网段上的路由器的router-id)
  • 产生者:DR(指定路由器)
  • OSPF网络和该网络上直接连接的路由器。它包含以下关键信息:
    -(Netmask),这里是255.255.255.0,用来定义网络的大小。

    • 附加路由器(Attached Router)列表,包括了所有直接连接到这个网络的路由器的IP地址。这些信息对于OSPF协议构建整个网络的拓扑图是必要的。
  • 范围:区域内。

LSA-type 2 (Network-LSA), len 36 
    .000 0000 0000 0001 = LS Age (seconds): 1 # LS年龄:1秒,该LSA存在于OSPF区域中的时间。
    0... .... .... .... = Do Not Age Flag: 0 # 不老化标志:0
    Options: 0x02, (E) External Routing # 选项:0x02,表示支持外部路由(E位)。
    LS Type: Network-LSA (2) # LS类型:网络LSA(2)
    Link State ID: 10.1.234.3 # 链路状态ID:10.1.234.3
    Advertising Router: 10.0.3.3 # 广告路由器:10.0.3.3 指发布此LSA的路由器IP地址。
    Sequence Number: 0x80000003 # 序列号:0x80000003
    Checksum: 0x25fb # 校验
    Length: 36 # 长度:36字节,表示整个LSA的长度。
    Netmask: 255.255.255.0 # 网络掩码:255.255.255.0,定义了网络的大小。
    
    
    #下面的这些路由器直连到了咱们的Area
    Attached Router: 10.0.3.3 # 附加路由器:10.0.3.3,直接连接的路由器。
    Attached Router: 10.0.1.1 # 附加路由器:10.0.1.1,直接连接的路由器。
    Attached Router: 10.0.2.2 # 附加路由器:10.0.2.2,直接连接的路由器。

LSA-TYPE 3

  • 对于类型 3 的 LSA(Summary-LSA),它们通常由 Area Border Routers (ABRs) 生成。ABR 负责在 OSPF 区域之间传递路由信息。
  • (DR) 主要用于管理类型 1 和类型 2 的 LSA(Router-LSA 和 Network-LSA)在 OSPF 区域内的传播,特别是在广播和非点对点多路访问网络中。DR 的角色通常与类型 3 LSA 的生成无关。
  • Link State ID:在类型 3 LSA 中,Link State ID 通常表示该 LSA 所描述的目标网络的 IP 地址。它提供了 LSA 所涉及的网络范围的信息。
  • 范围:area之间
LSA-type 3 (Summary-LSA (IP network)), len 28 # 网络摘要LSA,长度为28字节。
    .000 0010 0000 1010 = LS Age (seconds): 522 # LS年龄(秒):522,
    0... .... .... .... = Do Not Age Flag: 0 # 不老化标志:0,表示这个LSA会随时间老化。
    Options: 0x02, (E) External Routing # 选项:0x02,(E)表示支持外部路由。
    LS Type: Summary-LSA (IP network) (3) # LS类型:网络摘要LSA(类型3),用于在区域之间传播网络路由信息。
    Link State ID: 10.0.1.0 # 链路状态ID:10.0.1.0,通常是该LSA所描述的目标网络的IP地址。
    Advertising Router: 10.0.1.1 # 广告路由器:10.0.1.1,表示发布这个LSA的路由器的IP地址。
    Sequence Number: 0x80000001 # 序列号:0x80000001
    Checksum: 0x76cf # 校验和:0x76cf
    Length: 28 # 长度:28字节
    Netmask: 255.255.255.0 # 网络掩码:255.255.255.0,指示所描述网络的大小。
    TOS: 0 # TOS(Type of Service):0,表示服务类型,这里为默认值无意义内容。
    Metric: 0 # 度量值:0,表示到达所宣告网络的成本。

这里实际上描述了Area2

LSA-TYPE 4

  • 产生:它们是由区域内的每个路由器产生,用于通告到达 ASBR (Autonomous System Boundary Router,自治系统边界路由器) 的路由信息。ASBR 是那些连接到外部网络(如其他自治系统)的路由器。
  • Link State ID: ASBR的Router-id
  • Advertising Router: 谁吆喝的
  • 范围:OSPF内部

大体:内部的人找出口在哪

LSA-type 4 (Summary-LSA (ASBR)), len 28 
    .000 0001 1111 0100 = LS Age (seconds): 500 # LS年龄:500秒,
    0... .... .... .... = Do Not Age Flag: 0 # 不老化标志:0,表示该LSA会正常老化。
    Options: 0x02, (E) External Routing # 选项:0x02,表示支持外部路由(E)。
    LS Type: Summary-LSA (ASBR) (4) # LS类型:ASBR的Summary-LSA(4),表示这是一个总结LSA,用于描述到ASBR的路由。
    Link State ID: 10.0.5.5 # 链路状态ID:10.0.5.5,唯一标识这个LSA。 ASBR的Router-id
    Advertising Router: 10.0.3.3 # 广告路由器:10.0.3.3,表示发布这个LSA的路由器。
    Sequence Number: 0x80000001 # 序列号:0x80000001,用于确保LSA的更新能被正确识别。
    Checksum: 0xd136 # 校验和:0xd136
    Length: 28 # 长度:28字节
    Netmask: 0.0.0.0 # 网络掩码:0.0.0.0,对于类型4的LSA,通常设置为0。
    TOS: 0 
    Metric: 48 # 度量值:48,表示到达广告路由器的路径代价。

LSA-TYPE5

作用:描述AS外部路由信息(被引入的路由信息)告诉大家我是谁。
产生:ASBR
Link State ID:在AS-External-LSA中,Link State ID是与被广告路由相关的IP地址。它唯一标识了这个特定的LSA。
Advertising Router:是指生成并发送这个LSA的路由器。在AS-External-LSA的情况下,这通常是ASBR本身的IP地址。
范围:AS-External-LSA整个自治系统。它们被ASBR生成后,会在整个OSPF域中传播,以通知所有路由器关于外部(非OSPF)目的地的存在和路径。
感觉是相互广播。

LSA-type 5 (AS-External-LSA (ASBR)), len 36 # LSA类型5(AS外部LSA(ASBR)),
    .000 0001 1111 1111 = LS Age (seconds): 511 # LS年龄:511秒,
    0... .... .... .... = Do Not Age Flag: 0 
    Options: 0x02, (E) External Routing # 选项:0x02,(E)表示支持外部路由。
    LS Type: AS-External-LSA (ASBR) (5) # LS类型:AS外部LSA(ASBR)(5),表示这是一个描述自治系统外部路由的LSA。
    Link State ID: 10.0.35.3 # 链路状态ID:10.0.35.3,唯一标识这个LSA。
    Advertising Router: 10.0.5.5 # 广告路由器:10.0.5.5,表示发布这个LSA的路由器。
    Sequence Number: 0x80000001 
    Checksum: 0x404c 
    Length: 36
    Netmask: 255.255.255.255 # 子网掩码:255.255.255.255,表示路由的精确度。
    1... .... = External Type: Type 2 # 外部类型:类型2,表示这个LSA的度量值大于任何其他链路状态路径。
    .000 0000 = TOS: 0 # TOS:0,服务类型,这里为0。
    Metric: 1 # 度量:1,表示到达该目的网络的代价。
    Forwarding Address: 0.0.0.0 # 转发地址:0.0.0.0,用于指定数据包的下一跳地址。
    External Route Tag: 1 # 外部路由标签:1,可以用来传递附加信息,比如路由的来源。

LSA-TYPE5 LSA-TYPE7

类型5 LSA(AS-External-LSA):

  • 用途:用于在整个OSPF自治系统中宣告从非OSPF网络学习到的路由。这些LSA通常由ASBR(自治系统边界路由器)产生。
  • 传播范围:可以在整个OSPF区域内传播,除非被区域边界路由器(ABR)阻挡。
  • 适用场景:在标准OSPF环境中使用,尤其是当路由信息需要从ASBR传播到整个OSPF域时。

类型7 LSA(NSSA-External-LSA):

  • 用途:专门用于NSSA(不邻接存储区域)中。它允许在NSSA内部引入外部路由,同时不破坏NSSA的主要特性,即不允许普通的类型5 LSA进入。
  • 传播范围:类型7 LSA仅在NSSA内部传播。当它们到达NSSA的ABR时,ABR会将它们转换成类型5 LSA,以便在整个OSPF域中传播。
  • 适用场景:在特殊类型的OSPF区域(NSSA)中使用,允许在这些区域内部引入外部路由,同时限制这些路由的传播仅限于NSSA内部。

"不邻接存储区域"(Not-So-Stubby Area,NSSA)是一种特殊类型的区域在 OSPF(Open Shortest Path First)路由协议中使用。
NSSA 是为了解决标准存储区域(Stub Area)和完全存储区域(Totally Stub Area)的限制而设计的。

标准存储区域的限制:

  • 在标准存储区域中,外部路由(类型5 LSA)不被允许传入。这种区域只允许内部路由和到达自治系统边界路由器(ASBR)的默认路由。

NSSA的特性:

  • NSSA 允许在存储区域内引入外部路由。这是通过类型7 LSA(NSSA-External-LSA)实现的,它们在 NSSA 内部传播外部路由信息。
  • 类型7 LSA 在到达 NSSA 的区域边界路由器(ABR)时,会被转换成标准的类型5 LSA,然后在整个 OSPF 域中传播。

OSPF2-4

感觉也差不多。

1.拓扑结构中用到了OSPF的什么功能

  • 有4个AREA诶。多个区域(Area)
  • 区域边界路由器(Area Border Router, ABR)
  • 路由聚合:OSPF允许通过网络地址和掩码来聚合路由,这可以减少路由表的大小并减少区域间的路由信息交换。
  • Loopback接口:在OSPF中,loopback接口的IP地址经常被用作路由器的标识。图中显示了多个loopback接口的地址。

2.给出协议报文截图并进行分析。

感觉跟之前的也差不多?

随便分析一个bia:

LSA-type5:向外部宣告我是谁:

LSA-type 5 (AS-External-LSA (ASBR)), len 36
    .000 0001 1111 1111 = LS Age (seconds): 511
    0... .... .... .... = Do Not Age Flag: 0
    Options: 0x02, (E) External Routing
    LS Type: AS-External-LSA (ASBR) (5)
    Link State ID: 10.0.35.0
    Advertising Router: 10.0.5.5
    Sequence Number: 0x80000001
    Checksum: 0x5e31
    Length: 36
    Netmask: 255.255.255.0
    1... .... = External Type: Type 2 (metric is larger than any other link state path)
    .000 0000 = TOS: 0
    Metric: 1
    Forwarding Address: 0.0.0.0
    External Route Tag: 1

这样访问10.0.35.0/24需要通过10.0.5.5来访问。

当当:

OSPF VCs and Inter-Area Route Filtering

1.拓扑结构中用到了OSPF的什么功能

  1. OSPF VCs(Virtual Circuits):这是一种在不同区域之间建立虚拟链路的技术。OSPF VCs允许在不同OSPF区域之间建立逻辑上的连接,使得跨区域的路由信息可以互相传递。
  2. Inter-Area Route Filtering:这是一种通过过滤OSPF路由信息来控制区域间路由传播的方法。通过配置适当的过滤规则,可以限制某个OSPF区域向其他区域传播特定的路由信息。

2.给出协议报文截图并进行分析。

ENSP的虚拟路由器诶

从LS UPDATE里找:

有个P2P的子网

这里有个虚拟链路:

然后他有三个子网:

好像是说他可以建立虚拟链路。

AR1的PEER:

AR4的PEER:

好像也不是很多东西

AR4上有个vlink:

AR3上也有vlink:

AR2的OSPF brief:


[R2-ospf-1]display ospf brief

     OSPF Process 1 with Router ID 10.0.2.2
         OSPF Protocol Information

 RouterID: 10.0.2.2         Border Router:  AREA 
 Multi-VPN-Instance is not enabled
 Global DS-TE Mode: Non-Standard IETF Mode
 Graceful-restart capability: disabled
 Helper support capability  : not configured
 Applications Supported: MPLS Traffic-Engineering 
 Spf-schedule-interval: max 10000ms, start 500ms, hold 1000ms
 Default ASE parameters: Metric: 1 Tag: 1 Type: 2
 Route Preference: 10 
 ASE Route Preference: 150 
 SPF Computation Count: 14    
 RFC 1583 Compatible
 Retransmission limitation is disabled
 Area Count: 2   Nssa Area Count: 0 
 ExChange/Loading Neighbors: 0
 Process total up interface count: 4
 Process valid up interface count: 2
 
 Area: 0.0.0.0          (MPLS TE not enabled)
 Authtype: None   Area flag: Normal
 SPF scheduled Count: 14    
 ExChange/Loading Neighbors: 0
 Router ID conflict state: Normal
 Area interface up count: 3

 Interface: 10.0.2.2 (LoopBack0)
 Cost: 0       State: DR        Type: Broadcast    MTU: 1500  
 Priority: 1
 Designated Router: 10.0.2.2
 Backup Designated Router: 0.0.0.0
 Timers: Hello 10 , Dead 40 , Poll  120 , Retransmit 5 , Transmit Delay 1 

 Interface: 10.0.23.2 (Serial2/0/1) --> 10.0.23.3
 Cost: 48      State: P-2-P     Type: P2P       MTU: 1500  
 Timers: Hello 10 , Dead 40 , Poll  120 , Retransmit 5 , Transmit Delay 1 
 
 Area: 0.0.0.2          (MPLS TE not enabled)
 Authtype: None   Area flag: Transit
 SPF scheduled Count: 13    
 ExChange/Loading Neighbors: 0
 Router ID conflict state: Normal
 Area interface up count: 1

 Interface: 10.0.12.2 (Serial2/0/0) --> 10.0.12.1
 Cost: 48      State: P-2-P     Type: P2P       MTU: 1500  
 Timers: Hello 10 , Dead 40 , Poll  120 , Retransmit 5 , Transmit Delay 1 

这个图:

10.0.5.5 和 10.0.3.3之间有一条虚电路

不过虚电路到OSPF AREA 0 是如何交互数据的包我好像没太捕明白。

OSPF Troubleshooting

1.拓扑结构中用到了OSPF的什么功能

  • 多区域(Multi-Area)配置:图中显示了多个OSPF区域(AREA1, AREA2, 和 AREA0)。AREA0是OSPF的骨干区域,其他区域(如AREA1和AREA2)则是非骨干区域。这种设计可以减少路由更新的数量,从而降低CPU和内存的使用,提高网络稳定性。
  • 环回接口(Loopback Interfaces): 每个路由器都有一个环回地址,如10.0.1.1/24。在OSPF中,环回接口通常用来确保稳定的OSPF路由器ID,即使物理接口宕机,路由器ID也不会改变。
  • 路由器ID(Router IDs):每个路由器似乎都有一个明确的标识符,如AR1、AR2等。在OSPF中,这个ID通常是最高的活跃IP地址或者是手动配置的环回接口地址。
  • OSPF设计类型:尽管图中未明示,但路由器之间的连接可能表示点对点连接或广播网络。这些不同的网络类型在OSPF中会影响选举DR(指定路由器)和BDR(备份指定路由器)的行为。
  • LSDB(链路状态数据库):所有路由器在同一个OSPF区域中共享相同的LSDB,以确保所有路由器对网络拓扑有相同的视图。

2.给出协议报文截图并进行分析。

抓了两个路由器也都是只有hello报文

可能要修一下,但是不是很会华为的命令..

2-1Single-Area OSPF

1.拓扑结构中用到了OSPF的什么功能

这个就只有一个区域啦。

2.给出协议报文截图并进行分析。

跟之前的一样啦

之前已经提过了。这里就随便抓一个:

OSPF Header # OSPF报头
    Version: 2 # 版本号:2
    Message Type: LS Update (4) # 消息类型:LS更新(4)
    Packet Length: 156 
    Source OSPF Router: 10.0.1.1 # 来源OSPF路由器:10.0.1.1,标识发送此数据包的路由器的IP地址。
    Area ID: 0.0.0.0 (Backbone) # 区域ID:0.0.0.0,表示这是骨干区域的一个数据包。
    Checksum: 0xdd64 [correct] # 校验和:0xdd64,
    Auth Type: Simple password (1) # 认证类型:简单密码(1),表示使用了简单密码认证。
    Auth Data (Simple): huawei # 认证数据:'huawei',为密码认证的内容。

LS Update Packet # LS更新数据包,包含多个链路状态广告(LSA)的更新信息。
    Number of LSAs: 3 # LSA数量:3,表示此数据包包含3个链路状态广告。

    # 第一个LSA
    LSA-type 1 (Router-LSA), len 48
        LS Age: 1 # LS年龄:1秒,表示自LSA发布以来的时间。
        Do Not Age Flag: 0 # 不老化标志:0,表示该LSA会随时间老化。
        Options: (E) External Routing # 选项:(E) 外部路由,表示支持外部路由。
        LS Type: Router-LSA (1) # LS类型:路由器-LSA。
        Link State ID: 10.0.1.1 # 链路状态ID:10.0.1.1。
        Advertising Router: 10.0.1.1 # 广告路由器:10.0.1.1。
        Sequence Number: 0x80000007 # 序列号。
        Checksum: 0x9970 # 校验和。
        Length: 48 # 长度:48字节。
        Flags: 0x00 # 标志。
        Number of Links: 2 # 链接数量:2。
        Link details: # 链接详情。
            - Transit, ID: 10.0.123.3, Data: 10.0.123.1, Metric: 1 #直连
            - Stub, ID: 10.0.1.1, Data: 255.255.255.255, Metric: 0 #子网

    # 第二个LSA
    LSA-type 1 (Router-LSA), len 48 # 同上,不同的是Link State ID和Advertising Router变为10.0.3.3。

    # 第三个LSA
    LSA-type 2 (Network-LSA), len 32 # LSA类型:2(网络-LSA),长度:32字节。
        LS Age: 5 # LS年龄:5秒。
        Do Not Age Flag: 0 # 不老化标志:0。
        Options: (E) External Routing # 选项:(E) 外部路由。
        LS Type: Network-LSA (2) # LS类型:网络-LSA。
        Link State ID: 10.0.123.3 # 链路状态ID:10.0.123.3。
        Advertising Router: 10.0.3.3 # 广告路由器:10.0.3.3。
        Sequence Number: 0x80000001 # 序列号。
        Checksum: 0x1a8b # 校验和。
        Length: 32 # 长度:32字节。
        Netmask: 255.255.255.0 # 网络掩码。
        Attached Routers: # 附属路由器。
            - 10.0.3.3
            - 10.0.1.1

文件下载:

https://p.dabbit.net/ctf/实验10.rar

网络协议分析——实验九使用Wireshark分析TCP协议

文章在线:

https://cmd.dayi.ink/mXYpwNZfQXSEJWKHCoYAFg?both
https://type.dayiyi.top
https://blog.dayi.ink

实验目的

本实验旨在使用 Wireshark 工具分析 TCP 协议,包括抓取四种不同类型的 TCP 包并进行详细分析。

实验步骤

步骤1:准备工作

  • 打开 WireShark。
  • 尝试捕获

步骤2:抓取TCP数据包

  • 打开浏览器,访问一个 web 站点,然后关闭,重复操作以捕捉 TCP 数据包。
  • 筛选出其中一组 TCP 连接的管理过程。
  • 虽然可以随便抓,但是从HTTP/1.1开始访问一个网页可能会只建立一个TCP连接,可能会比较难抓,而且可能会同时建立更多的TCP包。
  • 我不太建议用浏览器,我不知道能不能正常抓到,或者虽然抓到了,但是有很多请求,于是难以筛选。打开浏览器之前尽量先加上筛选条件。

注意事项

  • HTTP/1.1 开始访问一个网页可能只会建立一个 TCP 连接,可能会比较难抓。
  • 在打开浏览器之前,加上筛选条件。

抓包分析

(1)TCP连接建立 (2)TCP连接断开 分析1 在windows下

  • 使用脚本模拟请求:

    #pip install requests
    import requests
    req = requests.get("http://wireshark.icee.top")
    req.encoding = "utf-8"
    print(req.text)

  • 使用 nslookup 命令查找要访问网址的 IP 地址以用于筛选:

    nslookup wireshark.icee.top
      nslookup [你要访问的网址]
      nslookup wireshark.icee.top

    这个查出来的IP就是等会要筛选的ip,方便来进行分析包

  • 筛选条件示例:

    ip.addr==43.128.1.238

这个包就很全,包含了建立建立连接和下载数据以及四(三)次挥手断开连接。

  • 过程如下:
  1. SYN:客户端(源IP地址为192.168.31.26,源端口为57619)向服务器(目的IP地址为43.128.1.238,目标端口为80,即HTTP服务)发送了一个TCP同步(SYN)报文,这是TCP三次握手的第一步,用于建立连接。
  2. SYN-ACK:服务器响应客户端的SYN请求,发送了一个SYN-ACK(同步应答)报文。这是三次握手的第二步,服务器确认接收到了客户端的同步请求。
  3. ACK:客户端再次发送ACK(确认)报文给服务器,完成三次握手,建立了TCP连接
  4. HTTP GET 请求:客户端在建立的TCP连接上发送了一个HTTP GET请求,请求从服务器获取特定的资源(通常是网页)。
  5. 服务器ACK:服务器确认收到了HTTP GET请求。
  6. HTTP响应:服务器处理了GET请求,并返回了一个HTTP 200 OK响应,表明请求成功,并附带所请求的资源内容。
  7. 客户端FIN:通信完成后,客户端发送了一个FIN(结束)报文,用于关闭连接。
  8. 服务器FIN:服务器同样发送了一个FIN报文,响应客户端的关闭请求。
  9. 最终ACK:最后,客户端发送了一个ACK报文来确认接收到了服务器的FIN报文,完成了整个TCP连接的终止过程。

挥手的时候:

  • FIN ACK
  • FIN ACK(服务器到客户端)
  • ACK

服务器的FIN和ACK合并在了一起,只发送了一个包,于是就只有3个。

8    0.146942    192.168.31.26    43.128.1.238    TCP    54    58035 → 80 [FIN, ACK] Seq=150 Ack=1093 Win=261888 Len=0
9    0.249596    43.128.1.238    192.168.31.26    TCP    54    80 → 58035 [FIN, ACK] Seq=1093 Ack=151 Win=64128 Len=0
10    0.249734    192.168.31.26    43.128.1.238    TCP    54    58035 → 80 [ACK] Seq=151 Ack=1094 Win=261888 Len=0

(1)TCP连接建立 (2)TCP连接断开 在linux下 分析2

在linux下好像跟windows的包有点不同,但都是服务器发过来的,应该跟操作系统没有关系。

这里我的抓包命令是:

sudo tcpdump tcp and host 43.128.1.238 -w capture_file.pcap

抓取的过程就仅抓与wireshark.icee.top服务器的交互

包1

另外一个包:

会发现,好像在结束TCP连接的时候会有所不同。

但是大差不大。

资料说:linux发送完最后的TCP会进入一个FIN_WAIT的阶段,但是windows会直接关上。

看的出来windows蛮着急的,linux就慢悠悠的。

  • windows恨不得3个包结束战斗,linux可能会等到全部资源一起结束了。

这段数据是网络数据包的捕获记录,显示了两个设备之间的通信过程。这里是一次典型的TCP(传输控制协议)连接过程,以及随后的HTTP(超文本传输协议)请求和响应。我将逐个解释这些包的作用:

  1. 包 1 - SYN

    • 动作: 客户端(192.168.106.128)向服务器(43.128.1.238)发送一个TCP同步(SYN)数据包,请求建立连接。
    • 详细: 客户端选择源端口48626,并且TCP序列号为0,表示这是一个新的连接请求。
  2. 包 2 - SYN, ACK

    • 动作: 服务器响应客户端的连接请求,发送一个SYN-ACK(同步应答)数据包。
    • 详细: 服务器确认(ACK)客户端的SYN请求,并提出自己的SYN请求。
  3. 包 3 - ACK

    • 动作: 客户端发送ACK(确认)数据包到服务器。
    • 详细: 这个ACK确认了服务器的SYN-ACK,三次握手过程完成,TCP连接建立。
  4. 包 4 - HTTP GET 请求

    • 动作: 客户端向服务器发送HTTP GET请求。
    • 详细: 请求获取服务器上的某个资源(如网页),通常URL会在HTTP头部中指定。
  5. 包 5 - ACK

    • 动作: 服务器发送ACK确认收到GET请求。
    • 详细: 这是对客户端HTTP请求的标准TCP确认。
  6. 包 6 - HTTP 200 OK 响应

    • 动作: 服务器回应HTTP请求,发送HTTP 200 OK响应,包含请求的数据(如网页内容)。
    • 详细: 数据包含所请求资源的内容
  7. 包 7 - ACK

    • 动作: 客户端确认收到HTTP响应。
    • 详细: 标准的TCP确认,表明客户端已成功接收数据包。
  8. 包 8 - FIN, ACK

    • 动作: 客户端发起关闭TCP连接的请求,发送FIN(结束)和ACK数据包。
    • 详细: 客户端表示已经完成数据的发送和接收,请求终止连接。
  9. 包 9 - ACK

    • 动作: 服务器确认收到了客户端的FIN请求。
    • 详细: 服务器通过发送ACK来响应客户端的终止请求。
  10. 包 10 - FIN, PSH, ACK

    • 动作: 服务器发送FIN和ACK,开始关闭连接的过程。
    • 详细: 服务器也表明了自己完成了数据的发送,希望关闭连接。
  11. 包 11 - ACK

    • 动作: 客户端确认收到服务器的FIN请求。
    • 详细: 这是对服务器关闭请求的最后确认,之后连接关闭。

数据传输

  1. HTTP GET 请求

    • 数据包4: 客户端发送了一个 HTTP GET 请求到服务器。
  2. ACK (Seq=1, Ack=45)

    • 数据包5: 服务器确认收到了 GET 请求。
  3. HTTP 响应

    • 数据包6: 服务器响应 HTTP 请求,状态码 200 OK,意味着请求已经成功处理。

填表:

连接建立报文段源端口目的端口序号确认号头部长度6个标志位中,值为1的窗口大小MSS选项
第1次48626800(2229626197)不适用(0)40SYN642401460
第2次80486260(241322383)1(2229626198)24SYN ACK642401460
第3次48626801(2229626198)1(241322384)20ACK64240不适用
……

连接断开报文段源端口目的端口序号确认号头部长度6个标志位中,值为1的窗口大小
第1次4862680150(2229626347)1093(241323476)20FIN,ACK63336
第2次80486261093(2229626348)151(241323476)20ACK64239
第3次80486261093(241323476)151(2229626348)20FIN,PSH,ACK64239
第4次4862680151(2229626348)1094(241323477)20ACK63336
……

(3)TCP重传尝试

  • 这个包你可以试试下着东西,然后拿着手机往外面跑。
  • 窗口调整的包我几乎没有抓到,但是也有!

  • 在网络质量较差的环境下抓包或使用 Linux 系统。
  • 使用 iptables 过滤 RST 包,以避免被内核重置。

    iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

    不加这行直接发包会被RST(linux内核发现来了个莫名其妙的包,于是发送了RST,TCP就没了)

  • 我这里写了个脚本,连接建立的包模拟了一下,但是可惜的断开连接的过程总是会有点问题,虽然发了包,但是服务器的断开四次挥手有点奇怪。

脚本只到建立TCP,然后挂起,不回复ACK,让服务器认为是包迟迟没有到达,于是不断发重传包。

from scapy.all import IP, TCP, send, sr1, Raw,socket,RandShort
from scapy.layers.http import HTTP, HTTPRequest

# 目标网址和端口
target = "wireshark.icee.top"
target_ip = socket.gethostbyname(target)
target_port = 80

# 创建IP包
ip = IP(dst=target_ip)

# 创建TCP SYN
tcp_syn = TCP(sport=RandShort(), dport=target_port, flags='S')
# 发送SYN并接收SYN-ACK
synack = sr1(ip/tcp_syn)
print(synack.show())
# 从SYN-ACK包中获取序列号,并构造ACK包
tcp_ack = TCP(sport=synack[TCP].dport, dport=target_port, flags='A', seq=synack[TCP].ack, ack=synack[TCP].seq + 1)

# 发送ACK包
send(ip/tcp_ack)

# 构造HTTP GET请求
get_str = 'GET /python-3.9.10-amd64.exe HTTP/1.1\r\nHost: ' + target + '\r\n\r\n'
get_str = 'GET / HTTP/1.1\r\nHost: ' + target + '\r\n\r\n'

http_get = ip / tcp_ack / Raw(load=get_str)

# 发送HTTP GET请求并等待响应
response = sr1(http_get, timeout=1)


# ACK回复已经收到的包
if response and HTTP in response:
    # ACK回复已经收到的包
    ack = TCP(sport=synack[TCP].dport, dport=target_port, flags='A', seq=response[TCP].ack, ack=response[TCP].seq + len(response[TCP].payload))
    send(ip/ack)
else:
    print("No HTTP response received")


# 构造TCP FIN包
tcp_fin = TCP(sport=tcp_ack.dport, dport=target_port, flags='FA', seq=tcp_ack.ack, ack=tcp_ack.seq + 1)
# 发送TCP FIN包
send(ip/tcp_fin)
# 接收服务器的ACK响应
ack_response = sr1(ip/tcp_fin, timeout=1)

if ack_response and TCP in ack_response and ack_response[TCP].flags == 'A':
    # 打印服务器的响应
    print(ack_response.show())
else:
    print("No ACK response received")

# 打印服务器的响应
print(ack_response)

# 不发送最终的ACK确认,触发重传
# 服务器应该会重传HTTP响应
# sudo tcpdump tcp and host 43.128.1.238 -w capture_file.pcap

# 休眠一会,等服务器的重传包(气死nginx)
# nginx超时时间在60s左右
import time
n = 40 
for i in range(n):
  print(f"sleeping {n-i}s..")
  time.sleep(1)
# 不发送最终的ACK确认,触发重传
# 休眠一会儿,等服务器的重传包
# time.sleep(30)  # 等待30秒来观察服务器的重传行为

对于捕获再开一个终端:

sudo tcpdump tcp and host 43.128.1.238 -w capture_file.pcap

抓到的包如下:

抓了好几天)

也有抓了之后尝试发送FIN,但是好像没太成功

筛选后比较满意的包:

填表:

因为是脚本生成的包(甚至后期直接把TCP填上了80发出去)所以确认号和相对号一样(因为一开始发出去的是0~)

TCP重传时间源端口目的端口序号确认号头部长度窗口大小
第1次0.1743068083521(3696288462)45(45)2064196
第2次0.1764568083521(3696288462)45(45)2064196
第3次0.4909428083521(3696288462)45(45)2064196
第4次1.0696158083521(3696288462)45(45)2064196
第5次2.2190138083521(3696288462)45(45)2064196
第6次4.5548978083521(3696288462)45(45)2064196
第7次9.1627578083521(3696288462)45(45)2064196
第8次18.378828083521(3696288462)45(45)2064196
第9次37.066628083521(3696288462)45(45)2064196

虽然一直丢失,但是重传的时间几乎是按照指数增加的。
1 2 4 8 16 32

TCP重传是一种错误控制机制,用于处理丢失或损坏的数据包。文本中的多个数据包(如Frame 6、7、8等)标记为“TCP Retransmission”,表明因为之前的包未能成功传输而重新发送的。实际上就是咱们故意不ACK然后他当然要重传,以为丢失了。

(4)滑动窗口

筛选条件:

tcp.analysis.ack_rtt

这样就有了。

但是整体的那个慢启动,拥塞避免,快重传、恢复,超时MSS设置为-1

如果WIRESHARK抓到了TCP建立过程,是可以把这个指数一起算出来的。

两方的MSS可以不相同。三次握手确定,可以避免在IP层被切片。

TCP滑动窗口机制:这是一种流量控制协议,用于确保发送方不会溢出接收方的缓冲区。文本提到需要对TCP滑动窗口机制进行分析,这通常涉及到监控发送和接收窗口的大小,以及如何根据网络条件动态调整这些窗口大小。

这种RST包就会直接windows设置为0

2.分析

TCP拥塞控制和流量控制

慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)和快速恢复(Fast Recovery)。

TCP拥塞控制的阶段

  1. 慢启动(Slow Start)

    • 在TCP连接刚建立时,拥塞窗口(cwnd)从一个较小的值(如1个MSS,最大报文段长度)开始。
    • 随着每个成功传输的轮回,窗口大小加倍,指数增长,直到达到一个阈值(ssthresh)。
  2. 拥塞避免(Congestion Avoidance)

    • 当拥塞窗口大小达到或超过ssthresh时,TCP进入拥塞避免阶段。
    • 在这一阶段,窗口大小增长变得更加保守,通常是线性增长。
  3. 快速重传(Fast Retransmit)

    • 当发送方收到三个重复的ACK时,意味着后面的包可能丢失,它将立即重传丢失的包,而不是等待超时。
  4. 快速恢复(Fast Recovery)

    • 在快速重传后,TCP进入快速恢复阶段。
    • ssthresh设置为当前拥塞窗口的一半,拥塞窗口设置为ssthresh加上重复ACK的数量,然后继续传输,如果收到新的ACK,则结束快速恢复,否则进入慢启动。

TCP流量控制的关键要素

TCP流量控制是一种确保发送方不会淹没接收方的机制,它利用滑动窗口协议来实现。

  1. 滑动窗口(Sliding Window)

    • 滑动窗口是TCP流量控制的核心,它控制着在等待确认之前可以发送的数据量。
    • 窗口大小(window size)是接收方根据自己的缓冲区大小动态通告给发送方的,表示接收方能够接收的数据量。
  2. 接收窗口(rwnd)

    • 接收窗口是接收方基于自己的处理能力和缓冲区大小告诉发送方的最大数据量。
    • 发送方必须确保未确认的数据总量不超过这个窗口大小。
  3. 调节窗口大小

    • 如果接收方处理能力较低或者缓冲区快满,它可以通过减小窗口大小通知发送方减缓发送速率。
    • 如果接收方的缓冲区空闲了,它可以增加窗口大小来接收更多数据。

分析数据

  1. 窗口大小的作用

    • 数据中窗口大小一直是64196。这表示接收方已经告诉发送方,在不收到进一步确认的情况下,它能够接受最多64196字节的数据。
  2. 流量控制与拥塞控制的区别

    • 尽管流量控制和拥塞控制都会影响发送方的发送速率。流量控制是为了避免发送方淹没接收方,而拥塞控制则是为了防止网络拥塞。
  3. 无窗口调节的迹象

    • 由于窗口大小没有变化,没有直接迹象表明接收方进行了窗口调节。这可能意味着接收方的处理能力和缓冲区空间在此期间保持相对稳定。
    • (这里也因为咱们没有去调节这个窗口,因为还要构造数据包)
  4. TCP拥塞控制机制的作用

    • TCP尝试通过重传丢失的包来恢复数据传输。
    • 持续的重传可能表明TCP尝试适应网络条件。
  • 数据包6-13: 显示了多次TCP重传,表明可能出现了网络拥塞或数据包丢失。TCP的拥塞控制机制会在检测到丢包时减少发送数据的速率。由于重复的TCP重传,表明一直未收到对先前数据包的确认。
  • 这里的“窗口大小”(Window Size)是流量控制的关键参数,表明接收端愿意接收的数据量。在这个过程中,窗口大小保持不变,表明接收端的接收能力没有变化。
  • TCP使用的是“加性增,乘性减”(AIMD)策略。在网络情况良好时逐渐增加窗口大小(增加传输速率),而在检测到丢包(如重传)时减小窗口大小(减少传输速率)。

TCP

  • 三次握手过程包括 SYN、SYN-ACK、ACK 包的交换。
  • 数据传输阶段涉及 HTTP GET 请求和 HTTP 响应。
  • 重传机制展示了 TCP 如何确保数据的可靠传输。
  • 流量控制和拥塞控制通过窗口大小和动态调整发送速率来应对网络状况。

TCP 三次握手过程

  1. SYN (Seq=0)

    • 数据包1: 客户端(10.1.1.117)向服务器(43.128.1.238)发送了一个 SYN 包以初始化连接。序列号为 0。
  2. SYN-ACK (Seq=0, Ack=1)

    • 数据包2: 服务器响应一个 SYN-ACK 包。这表示服务器接受了连接请求并且准备好进行通信。
  3. ACK (Seq=1, Ack=1)

    • 数据包3: 客户端回复一个 ACK 包,完成三次握手,建立连接。

窗口大小(Win)

TCP窗口大小是流量控制的一部分,指定了在等待确认之前可以发送的数据量(以字节为单位)。发送方根据接收方给出的窗口大小来决定发送的数据量。防止发送方过快地发送数据而使接收方处理不过来。

最大段大小(MSS)

最大段大小是TCP连接中可以发送的单个数据包的最大数据量。这个值通常在TCP三次握手期间的第一个SYN包中协商,是为了避免IP分片,因为IP分片会增加网络延迟和降低性能。

窗口缩放(WS)

窗口缩放是一个TCP选项,用于在流量控制中支持更大的窗口大小。因为原始的TCP窗口大小字段只有16位,最大值只能是65535字节。窗口缩放选项允许窗口大小值左移(乘以2的指数),使得最大窗口大小可以增加到1GB以上。

SEQ ACK

每个TCP段(数据包)都被赋予一个序列号,这样接收方就可以对接收到的数据进行排序,并检测重复或丢失的数据包。确认号则用于告知发送方哪些数据已经被成功接收。它通常是期望收到的下一个数据包的序列号。

当当

当当:

实验总结

  • 本实验通过 Wireshark 工具成功捕获并分析了 TCP 协议的运作机制。
  • 分析了 TCP 的三次握手、数据传输、重传机制以及流量控制和拥塞控制。

附录:

一个失败的脚本

from scapy.all import IP, TCP, send, sr1, Raw, socket, RandShort
from scapy.layers.http import HTTP, HTTPRequest
import time

# 目标网址和端口
target = "wireshark.icee.top"
target_ip = socket.gethostbyname(target)
target_port = 80

# 创建IP包
ip = IP(dst=target_ip)

# 创建TCP SYN
tcp_syn = TCP(sport=RandShort(), dport=target_port, flags='S')

# 发送SYN并接收SYN-ACK
print("[+] 发送SYN请求:")
print((ip/tcp_syn).show())
synack = sr1(ip/tcp_syn)
print("[+] 接收到SYN/ACK:")
print(synack.show())

# 从SYN-ACK包中获取序列号,并构造ACK包
print(f"[+] 构造ACK包:ack:[syn ack seq]+1 seq:[syn ack+1]:{synack[TCP].seq + 1}")
tcp_ack = TCP(sport=synack[TCP].dport, dport=target_port, flags='A', seq=synack[TCP].ack, ack=synack[TCP].seq + 1)

# 发送ACK包完成三次握手
print("[+] 发送ACK包:")
print((ip/tcp_ack).show())
send(ip/tcp_ack)

# 构造HTTP GET请求
print("[+] 构造HTTP请求:")
get_str = 'GET / HTTP/1.1\r\nHost: ' + target + '\r\n\r\n'
http_get = ip / tcp_ack / Raw(load=get_str)
print(f"[+] HTTP请求:{http_get.show()}")

# 发送HTTP GET请求并等待响应
print("[+] 发送HTTP请求并等待响应:")

response = sr1(http_get, timeout=5)
print("[+] 接收到HTTP响应:")
print(response.show())

print(f"ACK_dst_port:{synack[TCP].dport} Dport:{target_port}")
print("-----------------------")

# ACK回复已经收到的包
ack = TCP(sport=synack[TCP].dport, dport=target_port, flags='A', seq=response[TCP].ack, ack=response[TCP].seq + len(response[TCP].payload))
print("[+] 发送确认收到HTTP响应的ACK包:")
send(ip/ack)


# # 构造TCP FIN包
# tcp_fin = TCP(sport=synack[TCP].dport, dport=target_port, flags='FA', seq=response[TCP].ack, ack=response[TCP].seq + len(response[TCP].payload))
# print("[+] 发送TCP FIN包以开始断开连接:")
# fin_ack_response = sr1(ip/tcp_fin)
# print("[+] 接收到FIN-ACK响应:")
# print(fin_ack_response.show())

四次挥手没构建成功

先这样bia,数据够啦。

构建出来SEQ真的是0 哈哈哈哈哈

重传

尝试在网络质量差的环境下进行抓包,或者用linux


写了个脚本,结果被RST了

感觉是内核RST的。

脚本的包应该是正常发送,但是内核不知道脚本在做什么,然后接收到了个SYN ACK报文,于是不知道这是什么东西,直接发送了RST,然后这样脚本之后发的东西,服务器也觉得不知道什么东西,也直接RST了。

网上查了查,用iptables过滤了包就行大概?

apt-get install iptables
apt install python3-scapy

# 抓包命令(开另外一个ssh)
tcpdump tcp and host 43.128.1.238 -w capture_file.pcap
#用iptables把要发的RST包筛了去,这样就算收到奇怪的包也不会发RST。
iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

OK,这样没有RST包了


然后重新发送,并且只运行一次脚本

  • 在TCP连接中,每收到一个数据包,理论上应发送一个ACK包来确认收到。在实际操作中,TCP协议通常会通过延迟确认机制(Delayed ACK)来减少需要发送的ACK包数量。
  • TCP不会立即对每个接收到的数据包发送ACK,而是可能会延迟一段时间,直到收到更多数据包,或者达到一定的延迟时间阈值后,才发送一个ACK来确认多个数据包。

TCP 重传机制

  • 数据包7到13显示了多次 TCP 重传。网络中存在丢包、延迟或通信故障时。TCP 协议通过重传未被确认的数据包来确保数据的可靠传输。

流量控制和拥塞控制

  1. 流量控制 (Window Size)

    • TCP 使用窗口大小来控制数据传输的速率,以防止接收方的缓冲区被溢出。在这个例子中,窗口大小在不同的包中有所变化,如 Seq=1, Ack=45 时窗口大小为 64196。
  2. 拥塞控制

    • TCP 拥塞控制机制通过减少在网络中传输的数据量来应对网络拥塞。重传的包可能表明网络中存在拥塞问题,TCP 会动态调整其发送速率来适应网络状况。

抓包脚本1:

import requests
# encode = "utf-8"
req = requests.get("http://wireshark.icee.top",)
# print(req.encoding)
req.encoding = "utf-8"
print(req.text)
# req.encoding = "gbk"
print(req.text)

抓包脚本2:

已经再上文中啦

需要linux(且ROOT)环境

文件:

https://pic.icee.top/ctf/实验9文件.zip

大数据-笔记-1

文章地址:(可能更好的阅读体验)

  1. https://ovo.dayi.ink/2023/11/09/big%E6%95%B0%E6%8D%AE/
  2. https://www.cnblogs.com/rabbit-dayi/p/17822822.html
  3. https://type.dayiyi.top/index.php/archives/244/
  4. https://blog.dayi.ink/?p=93
  5. https://cmd.dayi.ink/-BShZBz_ThuNVoGepjYbsA (本文原始链接,打开速度可能偏慢)

1. 安装

2. 查看三台虚拟机IP

设置静态IP

3. 修改IPV4为manual

IP 地址如下:

gataway : 192.168.83.2
mask : 24
master: 192.168.83.10
slv1: 192.168.83.11
slv2: 192.168.83.12

3. 关闭防火墙

su
[输入密码:123456]
service iptable stop
service iptable status

===


slave1 slave2:


4.关闭防火墙自动运行

chkconfig iptables off
chkconfig --list | grep iptables

master:

slave1:

slave2:

5. 配置主机名

#hostname 
vi /etc/sysconfig/network
cat /etc/sysconfig/network
hostname dayi-bigdata-master
hostname dayi-bigdata-salve-1
hostname dayi-bigdata-salve-2

输入 i 进入编辑模式
输入 :wq 保存文件

发现已经做了)


master:

slave1:

![]

slave2:

6. IP 地址 HOSTNAME 绑定

vi /etc/hosts
192.168.83.XX master
192.168.83.xx slave1
192.168.83.xx slave2

i : 进入编辑模式
:wq : 保存文件

master:

slave1:

slave2

chk1:

7. 修改windows的host

打开文件

路径打开这个:

C:\Windows\System32\drivers\etc\

C:\Windows\System32\drivers\etc\hosts

先复制到桌面,然后修改完再复制回去(真就同步,我先想出来的pvp写的PVP)

8. 配置远程SSH登录

哦,直接登录

但是不是限制密钥登录..登不进去呀
哦哦,可以直接登录,那没事了

添加三个主机之后

ok)

锟斤拷烫烫烫

问题解决:

chk:

  1. windows 的hosts文件C:\Windows\System32\drivers\etc\
  2. 虚拟机的IP地址是否对应

三个节点窗口:

查看 -> 交互窗口 -> 右键底部的窗口,发送交互到所有标签

因为虚拟机里套虚拟机不好截图,菜单截不下来(


这个分割线没有用

我猜的

输入

ssh-keygen

生成RSA密钥:

复制公钥:

输入到虚拟机里的

.ssh/authorized_keys


9. 时钟同步

9.1 手动时间同步

su root
[输入密码:123456]
date #显示系统时间
hwclock --show #显示硬件时间
#如果时间不一样的话这样省事,直接NTP同步时间:
#设置硬件时钟调整为与本地时钟一致
timedatectl set-local-rtc 1
#设置时区为上海
timedatectl set-timezone Asia/Shanghai
ntpdate -u  pool.ntp.org
date
## 手动同步
date -s 20230907
date -s 9:40
hwclock --systohc

显示系统时间

显示系统硬件时间:

(全是锟斤拷)

NTP同步时间

9.2 自动时间同步

下班

2023年9月13日14:09:57
时间同步
timedatectl set-local-rtc 1
#设置时区为上海
timedatectl set-timezone Asia/Shanghai
ntpdate -u  ntp.aliyun.com
hwclock --systohc

9.3 配置自动时间同步

两个从节点

crontab -e 
# 输入i进行输入模式
# ctrl+shift+v 粘贴
0 1 * * * /usr/sbin/ntpdate ntp.aliyun.com
# 输入:wq 保存

10. 免密登录

#直接输入exit
# 或者
su dayi

10.1 设置SSH免密登录

ssh-keygen -t rsa
#然后回车3次就行了

cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
cat ~/.ssh/authorized_keys

我觉得这个公钥有点用:(应该没啥用了)
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6yR468UQBZ/9KSG71FD0UVlv9N0I6q2RfA94yLT7uGhja9vzBJSP9mDg8RF8+Z6p5+katfYE7YLzjtLNMtC5lTjkwW8WHFyCGUP0QEcAIH0ZdDVn3nwHG9k+b2XfpLNKOieWYqUoixRSzIecUd5iq3WDe4dUjgBmGhfouo+FtQob/q8OOg2iJszl86ad8dE9W2BRS3VU5q6/OZmPp8uJcfXAl4/bHJq56+FNPSwk9b+umAsiH+bqeVCkW6JJd/Tw7DGkhYACGxleF5onBtiLKwbMZ+RanWiFm9AZqod86rcmZ9IPYaWf/QXgyun5vrNBBgBT+a8CBsRoBpFk0X7CCw== dayi@dayi-bigdata-master


ssh-copy-id dayi-bigdata-slave-1
ssh-copy-id dayi-bigdata-slave-2

10.2 测试是否免密登录

ssh dayi-bigdata-slave-1
# 退出 exit 或者 ctrl+d
ssh dayi-bigdata-slave-2
# 退出 exit 或者 ctrl+d

11. 安装JDK(普通用户)

新建文件夹

cd ~
mkdir -p ~/resources
cd ~/resources

复制文件
sftp://dayi-bigdata-master
sftp://dayi-bigdata-slave-1
sftp://dayi-bigdata-slave-2

查看下当前的文件

ls 

[dayi@HOSTNAME=dayi-bigdata-slave-2 resources]$ ls
jdk-7u71-linux-x64.gz
[dayi@HOSTNAME=dayi-bigdata-slave-2 resources]$ 

解压

tar -zxvf jdk-7u71-linux-x64.gz 
# 重命名
mv jdk1.7.0_71 jdk

11.1 配置环境变量

# (可选,出错请忽略)按老师目录移动文件
mv ~/Home/resources ~/resources
vim ~/.bash_profile
#按 i 输入
export JAVA_HOME=~/resources/jdk
export PATH=.:$JAVA_HOME/bin/:$PATH
#input: :wq (保存)
source .bash_profile

11.2 验证JDK安装成功

java -version

12. 安装hadoop(master 普通用户)

只做主节点。

tar -zxvf hadoop-2.6.4.tar.gz 
mv hadoop-2.6.4 hadoop

编辑bash配置 文件


# 记得在普通用户下
vim ~/.bash_profile

# i 输入

# 编辑模式下ctrl+shift+v
export HADOOP_HOME=~/resources/hadoop
export PATH=$PATH:$HADOOP_HOME/bin

#:wq保存文件

np++连接

  • 打开notepad++

输入配置文件

点这个

然后到这里来:

/home/dayi/resoureces/hadoop/etc/hadoop

修改hadoop-env.sh

hadoop-env.sh 25 行

export JAVA_HOME=~/resources/jdk

修改 yarn-env.sh

yarn-env.sh

  • 23 行
export JAVA_HOME=~/resources/jdk

修改 core-site.xml

core-site.xml

<configuration>
  <property>
    <name>fs.defaultFS</name>     
    <value>hdfs://master:9000</value>   
  </property>
  <property>
    <name>hadoop.tmp.dir</name>     
    <value>/home/wg/resources/hadoopdata</value>   
  </property>
</configuration>

新建data文件夹

# 记得自己改
mkdir -p /home/dayi/resources/hadoopdata

修改hdfs-site.xml

<property>
   <name>dfs.replication</name>
   <value>2</value>
</property>

ctrl+s

修改yarn-site.xml

<configuration>
<!-- Site specific YARN configuration properties -->
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
  <property>
   <name>yarn.resourcemanager.address</name>
   <value>master:18040</value>
  </property>
  <property>
    <name>yarn.resourcemanager.scheduler.address</name>
    <value>master:18030</value>
  </property>
  <property>
    <name>yarn.resourcemanager.resource-tracker.address</name>
    <value>master:18025</value>
  </property>
  <property>
    <name>yarn.resourcemanager.admin.address</name>
    <value>master:18141</value>
  </property>
  <property>
    <name>yarn.resourcemanager.webapp.address</name>
    <value>master:18088</value>
  </property> 
</configuration>

修改mapred-site.xml

  • 打开mapred-site.xml.template
  • 新建文件:

  • 输入内容

<configuration>
 <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
</configuration>

打开slaves

添加

slave1
slave2

将配置好点hadoop发送到从节点

cd ~
cd resources
scp -r 

scp -r hadoop dayi-bigdata-slave-1:~/resources/hadoop/
scp -r hadoop dayi-bigdata-slave-2:~/resources/hadoop/

13.启动hadoop

  1. 格式化文件系统(master,普通用户
hadoop namenode -format

  1. 启动hadoop
cd ~/resources/hadoop/sbin/

./start-all.sh


~/resources/hadoop/sbin/./start-all.sh

  1. check
jps

http://master:50070

13.1 验证

#启动
~/resources/hadoop/sbin/./start-all.sh

http://master:50070

13.2 修复

~/resources/hadoop/sbin/./stop-all.sh

rm -rf ~/resources/hadoopdata
rm -rf ~/resources/hadoop/logs

hadoop namenode -format

~/resources/hadoop/sbin/./start-all.sh

结果:

14 HDFS

先保证你的节点有两个以上哦

  1. 浏览文件
hadoop fs -ls /

好像没什么东西

这里好像也可以看:

http://master:50070/explorer.html#/

  1. 创建目录
# 创建目录
hadoop fs -mkdir /ovo
hadoop fs -mkdir /a

# 查看目录/
hadoop fs -ls /

主页查看文件

  1. 上传文件?

1) 本地新建一个文件

也可以直接图形界面去干

```bash
cd ~
mkdir b
ls -alh b
cd b
echo ovo>>ovo.txt

# i 输入  esc->:wq 保存
vi test
```

![](https://cmd.dayi.ink/uploads/upload_c1cafce09bba6934b540c701cfa2c204.png)

查看目录和文件:

```bash
ls -alh
cat test
```

![](https://cmd.dayi.ink/uploads/upload_1d3f01c459a875aa64618932d49293d8.png)

2) 将test上传到文件系统

cd ~/b
hadoop fs -put test /a
hadoop fs -ls /a
#或者主页打开

  1. 查看文件内容
hadoop fs -cat /a/test
hadoop fs -text /a/text

  1. 下载文件
hadoop fs  -get /a/test test1
ls -alh
cat test1

  1. 修改文件权限
hadoop fs -ls /a
hadoop fs -ls /

hadoop fs -chmod +? 

-rw-r--r--

- 文件/目录


rwx : read write exce(执行)

rw- : 用户权限 (u) 
r-- : 组权限 (g)
r-- : 其他人权限 (o)

增加执行权限:

hadoop fs -chmod u+x /a/test
hadoop fs -ls  /a

组权限+wx
other权限+wx

hadoop fs -chmod o+x /a/test
hadoop fs -chmod g+x /a/test
hadoop fs -ls  /a

去除所有人的执行权限

hadoop fs -chmod a-x /a/test
hadoop fs -ls  /a

数字:

000
rwx

自由组合,二进制转十进制

比如全部权限

111 = 2^0+2^1+2^2=1+2+4=7
rwx

权限

hadoop fs -chmod 644 /a/test

#很危险的操作哦)容易被黑掉
hadoop fs -chmod 777 /a/test

hadoop fs -ls  /a

hadoop fs -chmod 644 /a/test

  1. 删除文件
hadoop fs -rm /a/test

  1. 删除目录
hadoop fs -rm -r /a
hadoop fs -ls /

15. mysql安装?

  1. 新建mydb文件

普通用户

mkdir ~/resources/mydb
  1. 复制文件,把文件粘贴进去
能直接粘贴到虚拟机就不用这个

这里软件是filezila

如何连接:

  1. 检查系统里是否有自带的mysql
su

rpm -qa | grep -i mysql

有一个诶

  1. 有的话就删除
建议打个快照先
rpm -e mysql-libs-5.1.71-1.el6.x86_64 --nodeps

#然后看看还有没有

rpm -qa | grep -i mysql

  1. 安装4个文件

common , libs , client, server

#(在普通用户下)
su dayi(按你用户名)
cd ~
su 
cd resources/mydb
ls -al

安装:

rpm -ivh mysql-community-common-5.7.13-1.el6.x86_64.rpm
rpm -ivh mysql-community-libs-5.7.13-1.el6.x86_64.rpm
rpm -ivh mysql-community-client-5.7.13-1.el6.x86_64.rpm
rpm -ivh mysql-community-server-5.7.13-1.el6.x86_64.rpm

  1. 启动server
service mysqld start 

修改mysql默认密码


service mysqld start
sudo cat /var/log/mysqld.log | grep 'temporary password' 

mysql -uroot -p"di<aPM7a&p/("

修改密码:
用户名:root
密码:wg1%Bigdata

ALTER USER 'root'@'localhost' identified by 'wg1%Bigdata'; 

OK 就可以

mysql中创建用户

用户名: hadoop
密码: hadoop1%Bigdata

Grant all on *.* to 'hadoop'@'%' identified by 'hadoop1%Bigdata';
grant all on *.* to hadoop@'localhost' identified by 'hadoop1%Bigdata';
grant all on *.* to hadoop@'master' identified by 'hadoop1%Bigdata';
flush privileges;

尝试登录

quit;
su dayi
mysql -uhadoop -p"hadoop1%Bigdata"

MYSQL数据库里创建hive元数据库,叫hive1

查看当前数据库

show databases;

创建数据库

create database hive1;
show databases;
quit;

16. 安装hive

1.复制hive文件到resources

2.解压缩

#进入目录
cd ~/resources
# 解压缩
tar -zxvf apache-hive-1.2.1-bin.tar.gz
# 重命名(移动)
mv apache-hive-1.2.1-bin hive

3. NPP改配置文件

连接:

打开目录:~/resources/hive/conf

新建文件,右键文件夹hive-site.xml

内容如下:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration> 
  <property> 
    <name>hive.metastore.local</name> 
    <value>true</value> 
  </property> 
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://master:3306/hive1?characterEncoding=UTF-8</value>
   </property> 
   <property> 
      <name>javax.jdo.option.ConnectionDriverName</name>
      <value>com.mysql.jdbc.Driver</value> 
   </property> 
   <property>
      <name>javax.jdo.option.ConnectionUserName</name> 
      <value>hadoop</value> 
   </property> 
   <property> 
      <name>javax.jdo.option.ConnectionPassword</name> 
      <value>hadoop1%Bigdata</value> 
   </property> 
</configuration>

如果你的主机名不一样记得改这行:
jdbc:mysql://master:3306/hive1?characterEncoding=UTF-8

jdbc:mysql://master:3306/hive1?characterEncoding=UTF-8
driver      host    port database_name  
            
hadoop 用户名
hadoop1%Bigdata 密码

4. 复制驱动

mysql-connector-java-5.1.42-bin.jar -> ~/resources/hive/lib

5.配置bash

配置环境变量

  • npp
vim ~/.bash_profile

#添加这两行
export HIVE_HOME=~/resources/hive
export PATH=$PATH:$HIVE_HOME/bin

# 重载配置文件
source ~/.bash_profile

然后查看hive版本,如果能查看就说明环境目录成功了

hive --version

搞得和预言家一样

6. 替换文件

rm ~/resources/hadoop/share/hadoop/yarn/lib/jline-0.9.94.jar
cp ~/resources/hive/lib/jline-2.12.jar ~/resources/hadoop/share/hadoop/yarn/lib/

7. 启动hive

#1.下载原神(hadoop)
~/resources/hadoop/sbin/./start-all.sh

#2. 安装原神(mysqld)
service mysqld start

#3.启动原神
hive

原神:

8.启动

~/resources/hadoop/sbin/./start-all.sh
service mysqld start
hive

CRT 调整:

17.hive应用

hive>quit;

1. 新建文件

cd ~
mkdir cc
cd cc
vi stu

i 输入 ESC+:wq保存

查看文件

cat stu

2.启动hive

hive

命令:

  • 查看数据库

    show databases;

  • 创建数据库

    create database studb;
    show databases;

  • 切换数据库

    use studb;

  • 查看当前数据库里的表

    show tables;

  • 创建表
    \t来区分列

    create table if not exists stu
    (name string,age int,sex string)
    row format delimited fields terminated by '\t';
    show tables;

    查看文件:
    http://master:50070/explorer.html#/user/hive/warehouse/studb.db/

  • 查看表的创建信息等

    show create table stu;

  • 查看表结构

    desc stu;

3. 加载数据

在hive下
  • 从文件加载数据

    load data local inpath '/home/dayi/cc/stu' into table stu;

  • 查询表

    select * from stu;

  • 删除表

    drop table stu;

  • 删库跑路

    database没有表,为空
    drop database studb;

    有表的情况下
    drop database studb cascade;

4. 大数据分析-hive应用2

搜狗

ts    搜索时间
uid    用户id
kw    用户搜索的关键字
rank    搜索结果排序
orders    点击次数
url    访问的路径

创建

create database sogoudb;
show databases;

使用数据库

use sogoudb;

创建外部表

create external table if not exists sogou
(ts string,uid string,kw string,rank int,orders int,url string)
row format delimited fields terminated by '\t'
location '/s1/sogoudata';

查看表

show tables;
desc sogou;

加载数据方式2

把这个500M文件(sogou.500w.utf8)塞到cc目录(~/cc)

查看文件

cd ~/cc
ls -alh

上传文件

#上传文件(好慢)
hadoop fs -put sogou.500w.utf8 /s1/sogoudata
#查看文件
hadoop fs -ls /s1/sogoudata

http://dayi-bigdata-master:50070/explorer.html#/s1/sogoudata

进入hive-导入

在hive里
use sogoudb;

查询记录-前三条

select * from sogou limit 3;

查询表里总共多少记录

select count(*) from sogou;

超级慢

193秒:

查询UID总数

select count(distinct(uid)) from sogou;

还没执行完

177秒

select count(uid) from sogou 
group by uid;

出来了:

统计用户平均查询次数

$平均次数=总次数/用户个数$

建立临时表:

a

uidcnt
a10
b20

总次数 = sum(a.cnt)
用户个数 = count(a.uid)

临时表a

select uid,count(*) as cnt
from sogou
group by uid;

总表:

select sum(a.cnt)/count(a.uid) from
(select uid,count(*) as cnt
from sogou
group by uid)as a;

开炮:

好慢:

出了

3.6964094557111005

查询频度最高的前10个关键字

SELECT kw, COUNT(kw) AS cnt
FROM sogou
GROUP BY kw
ORDER BY cnt DESC
LIMIT 10;

那个URL

好慢hhhh:

出来了:

18. zookeeper

1. 复制压缩包

cd resources
tar -zxvf zookeeper-3.4.6.tar.gz
mv zookeeper-3.4.6 zookeeper

recources/zookeeper/conf

文件zoo.cfg

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=master:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888

server.1 服务器编号

master 服务器名

2888 服务端口

3888 选举端口

3.创

数据节点表示文件myid

位置 dataDir=/tmp/zookeeper

#位置在内存盘里 重启会丢失
mkdir -pv /tmp/zookeeper
cd /tmp/zookeeper
vi myid
输入1
然后ESC + :wq

# 那样建议这样写

#master
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 1 > myid
cat /tmp/zookeeper/myid

#slave1
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 2 > myid
cat /tmp/zookeeper/myid
#slave2
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 3 >myid
cat /tmp/zookeeper/myid

服务器炸了虚拟机没了

4. 发送zookeeper发送到从节点


cd ~/resources/
ls

scp -r zookeeper slave1:~/resources/
scp -r ~/resources/zookeeper slave2:~/resources/

5. 传送bash_profile

scp -r ~/.bash_profile slave1:~/
scp -r ~/.bash_profile slave2:~/


# 从节点分别执行:
source ~/.bash_profile

6. 启动zookeeper

cd ~/resources/zookeeper/bin/
ls 
./zkServer.sh start

#一键
~/resources/zookeeper/bin/./zkServer.sh start

跟上了

验证启动


./zkServer.sh status

这样是正常的


炸了

调试(zkServer.sh print-cmd)

"/home/dayi/resources/jdk/bin/java" -Dzookeeper.log.dir="." -Dzookeeper.root.logger="INFO,CONSOLE" -cp "/home/dayi/resources/zookeeper/bin/../build/classes:/home/dayi/resources/zookeeper/bin/../build/lib/*.jar:/home/dayi/resources/zookeeper/bin/../lib/slf4j-log4j12-1.6.1.jar:/home/dayi/resources/zookeeper/bin/../lib/slf4j-api-1.6.1.jar:/home/dayi/resources/zookeeper/bin/../lib/netty-3.7.0.Final.jar:/home/dayi/resources/zookeeper/bin/../lib/log4j-1.2.16.jar:/home/dayi/resources/zookeeper/bin/../lib/jline-0.9.94.jar:/home/dayi/resources/zookeeper/bin/../zookeeper-3.4.6.jar:/home/dayi/resources/zookeeper/bin/../src/java/lib/*.jar:/home/dayi/resources/zookeeper/bin/../conf:"  -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain "/home/dayi/resources/zookeeper/bin/../conf/zoo.cfg"

然后直接复制启动(你的跟我的不一样)

在这里看看报错是什么

出现错误看看这个文件是否正常

/tmp/zookeeper/myid

19. 安装hbase

1. 复制文件解压缩

cd ~/resources/
tar -zxvf hbase-0.98.9-hadoop2-bin.tar.gz
mv hbase-0.98.9-hadoop2 hbase

2. 修改配置文件

文件1

~/resources/hbase/conf/hbase-env.sh

29 行:

获得JAVA_HOME:

echo $JAVA_HOME

124行:

true : 使用habase自带的ZK(你启动失败了zookeeper)

false : 不使用hbase自带的ZK (上节课启动成功)

文件2

~/resources/hbase/conf/hbase-site.xml

<configuration>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.rootdir</name>
<value>hdfs://master:9000/hbase</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
</configuration>

文件3

regionservers

3. 添加环境变量

export HBASE_HOME=~/resources/hbase
export PATH=$PATH:$HBASE_HOME/bin
export HADOOP_CLASSPATH=$HBASE_HOME/lib/*

保存后,sources一下

两个从节点:

source ~/.bash_profile

4. 传送文件

scp -r ~/resources/hbase slave1:~/resources/
scp -r ~/resources/hbase slave2:~/resources/
scp -r ~/.bash_profile slave1:~/
scp -r ~/.bash_profile slave2:~/

source一下

#slave1
source ~/.bash_profile
#slave2
source ~/.bash_profile

5. 原神启动

hadoop

~/resources/hadoop/sbin/./start-all.sh

验证:
http://master:50070

这种情况重新执行一下就行

zookeeper

#master
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 1 > myid
~/resources/zookeeper/bin/./zkServer.sh start
#slave1
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 2 > myid
~/resources/zookeeper/bin/./zkServer.sh start
#slave2
mkdir -pv /tmp/zookeeper && cd /tmp/zookeeper && echo 3 >myid
~/resources/zookeeper/bin/./zkServer.sh start

验证:

~/resources/zookeeper/bin/./zkServer.sh status


lader or following

hbase

~/resources/hbase/bin/start-hbase.sh

验证:
http://master:60010

20. hbase使用

1. shell

hbase shell

2. CRT

3. 命令1 list

4. 命令2 新建表

create 'stu','info','score'

        表名    列族1  列族2

4. 命令3 写数据

尽量不要超过三列

put 'stu','1','info:name','John'

put 'stu','2','info:age',20
put 'stu','3','info:name','Mary'
put 'stu','3','info:age',19


put 'stu','3','score:math',90

5. 读数据

两种方式

get 'stu','1'

get 'stu','3'

scan 读所有行

scan 'stu'

查看表结构

describe 'stu'

Table stu is ENABLED                                                                                                                                                                                            
COLUMN FAMILIES DESCRIPTION                                                                                                                                                                                     
{NAME => 'info', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS => 'FALSE', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}                                                                                                                                                 
{NAME => 'score', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS => 'FALSE', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}                                                                                                                                                
2 row(s) in 0.0680 seconds

6. 删除

删单元格

delete 'stu','3','score:Math'

删除失败好像不会报错。

删行

deleteall 'stu','2'
scan 'stu'

删表

  1. 先让表失效
  2. 删除表
disable 'stu'
drop 'stu'
 list

20 MapReduce

肚子疼死了
拉肚子拉的有点自闭,上课没跟上

1. 安装JDK

jdk-8u102-windows-x64.exe
安装目录不要带有中文,可以的话推荐选择
C:\Program Files\Java或者D:\Program Files\Java
有闸瓦环境了非1.8版本也建议再装一个。

2. 解压缩hadoop

  1. 想法子把这个文件hadoop-2.6.4.tar.gz解压了

  1. 推荐放到目录:D:\hadoop\hadoop-2.6.4

  1. 然后修补下hadoop

需要替换文件直接替换即可。

D:\hadoop\hadoop-2.6.4\bin里面放下:

  • hadoop-common-2.2.0-bin-master.zip里面的bin目录(替换文件)。
  • hadoop.dll 放入 D:\hadoop\hadoop-2.6.4\bin (替换)
  • winutils.exe 放入 D:\hadoop\hadoop-2.6.4\bin (替换)

3. 配置环境变量

这一步就是加4个(3个)环境变量,没那么复杂,但是会根据你电脑的实际情况有所不一样。所以篇幅比较大

如何修改环境变量?
此电脑/这台电脑/计算机(在文件管理器里,防止你桌面的是个快捷方式)->右键 属性-> 找到高级系统设置 —> 高级 -> 环境变量
最后的5

按你实际修改目录,用户变量和系统变量都可以。

好像如果JAVA_HOME目录有空格的话会有些问题,

  • JAVA_HOME : C:\Program Files\Java\jdk1.8.0_102
  • classpath : .;C:\Program Files\Java\jdk1.8.0_102\lib\dt.jar;C:\Program Files\Java\jdk1.8.0_102\lib\tools.jar;C:\Program Files\Java\jdk1.8.0_102\bin
  • HADOOP_HOME: D:\hadoop\hadoop-2.6.4
  • Path(不要跟*天宇一样直接删了再加,在原来的基础上修改,你的系统不应该没有这个环境变量参数(Path),请先找找,这个环境变量是有顺序的,前面的会优先遍历) :

    • 这种的添加;C:\Program Files\Java\jdk1.8.0_102\bin\;D:\hadoop\hadoop-2.6.4\bin
    • 这种的新建两个条目,移动到最上面去

      • C:\Program Files\Java\jdk1.8.0_102\bin\
      • D:\hadoop\hadoop-2.6.4\bin

  • 验证环境变量
java -version
echo %JAVA_HOME%
ECHO %HADOOP_HOME%
hadoop verison

D:\jdk\jdk1.8.0_102

遇到这个问题:

我也不知道影不影响,原因是:Program Files中存在空格,然后他不能正常用,两个方法:

  • 方法1:把JAVA_HOME环境变量中的Program Files改为:PROGRA~1,比如这里我改为了:C:\PROGRA~1\Java\jdk1.8.0_102
  • 方法2(推荐):把JDK复制一份到普通目录中(不带空格),然后修改JAVA_HOME到这里

  • 方法三:虽然我带着的空格,但是跑起来很正常,老师跟我说是这样(求告知)
他这个JAVA_HOME的路径带空格好像会奇奇怪怪的

改成JAVA_HOME = "C:/xxxxx/jre1.8_102"(带引号会这样)

复制了jdk到没空格的目录
把hadoop的env

这样好像可以
感觉不应该呀,带空格就识别不出来感觉不至于有这种低级问题bia

  • 也可以尝试修改这个文件的25行D:\hadoop\hadoop-2.6.4\etc\hadoop\hadoop-env.cmd

总之:
执行:

java -version
echo %JAVA_HOME%
ECHO %HADOOP_HOME%
hadoop verison

第一行和最后一行的结果应该这样,但是你的如果有点多余的东西,应该也不是很影响?

4. 新建项目

1. 配置Eclipse

感谢王策哥哥

windows->preference->java->install JREs->add->standard VM

2. 新建工程

感谢王策
file->new project->java project->next->name->finish

3. 导包

  1. ALT+ENTER 打开项目设置
  2. JAVA BUILD PATH -> 添加外部库
  3. 导入hadoop环境jar包
D:\hadoop\hadoop-2.6.4\share\hadoop\common所有jar包
D:\hadoop\hadoop-2.6.4\share\hadoop\common\lib所有jar包

D:\hadoop\hadoop-2.6.4\share\hadoop\hdfs所有jar包
D:\hadoop\hadoop-2.6.4\share\hadoop\hdfs\lib所有jar包

D:\hadoop\hadoop-2.6.4\share\hadoop\mapreduce所有jar包
D:\hadoop\hadoop-2.6.4\share\hadoop\mapreduce\lib所有jar包

D:\hadoop\hadoop-2.6.4\share\hadoop\yarn所有jar包
D:\hadoop\hadoop-2.6.4\share\hadoop\yarn\lib所有jar包

5. 新建包

新建org.apache.hadoop.io.nativeio

org.apache.hadoop.io.nativeio

然后把NativeIO.java弄到包里

可以直接拖过来

新建包 my

my

同样的,把文件弄过去

如果需要修改的话这里:

到master下修改下目录权限

master

#启动hadoop
~/resources/hadoop/sbin/./start-all.sh

看看网页:
http://master:50070/dfshealth.html#tab-datanode

正常的话,
设置777权限

hadoop fs -chmod 777 /

6. 尝试新建目录

运行Test.java

这样就好啦

单词统计

  • 21 行 可能需要重新配置

存放数据源

master

mkdir -pv ~/aa
cd ~/aa
vim ~/aa/words
cat ~/aa/words

[dayi@dayi-bigdata-master aa]$ cat ~/aa/words
ovo ovo
Hello words
Pig man
ZOOKEEPER
HADOOP
Hello words
ovo ovo
Zhangsan like pigman
Do u wanna build a snowman?
Come on let’s go and play!
I never see you anymore
come out the door

上传words

  • 目录是否正常
hadoop fs -ls /

Found 6 items
drwxr-xr-x   - dayi          supergroup          0 2023-10-26 17:09 /hbase
drwxr-xr-x   - dayi          supergroup          0 2023-10-11 14:43 /ovo
drwxr-xr-x   - dayi          supergroup          0 2023-10-18 23:40 /s1
drwx-wx-wx   - dayi          supergroup          0 2023-10-18 23:57 /tmp
drwxr-xr-x   - dayi          supergroup          0 2023-10-18 23:01 /user
drwxr-xr-x   - Administrator supergroup          0 2023-11-01 23:37 /ww
[dayi@dayi-bigdata-master aa]$ 

要有这个/ww目录
没有的话

hadoop fs -mkdir /ww
hadoop fs -chmod 777 /ww
  • 上传文件
hadoop fs -put ~/aa/words /ww
hadoop fs -cat /ww/words

运行程序

查看文件:

http://master:50070/explorer.html#/ww/result

21 mapperreduce 代码

读取文件

package my;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;

public class ReadData {
 public static void main(String[] args) throws Exception{
  String hdfs_addr = "hdfs://dayi-bigdata-master:9000";
  String uriSrting=hdfs_addr +"/ww/words";
  Configuration config = new Configuration();
  FSDataInputStream inputStream=null;
  try{
   FileSystem fileSystem = FileSystem.get(URI.create(hdfs_addr),config);
   inputStream = fileSystem.open(new Path(uriSrting));
   IOUtils.copyBytes(inputStream, System.out, 4096,false);
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   IOUtils.closeStream(inputStream);
  }
 }
}

新建目录

上传文件

package my;

import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class PutFile {
  public static void main(String[] args) {
    String hdfs_addr = "hdfs://dayi-bigdata-master:9000";
    try{
      FileSystem fileSystem = FileSystem.get(URI.create(hdfs_addr),new Configuration());
      Path src = new Path("C:\\Windows\\System32\\drivers\\etc\\hosts");
      Path desc=new Path(hdfs_addr+"/ww/ff");
    fileSystem.copyFromLocalFile(src, desc);
    }catch (Exception e){
      e.printStackTrace();
    }
  }
}

下载文件

hadoop fs -chmod 777 /ww/ff
package my;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;

public class GetFile {
  public static void main(String[] args) throws IOException {
    String hdfs_addr = "hdfs://dayi-bigdata-master:9000";
    // FileSystem fileSystem = new FileSystem.get(URI.create(hdfs_addr),new Configuration());
    FileSystem fileSystem=FileSystem.get(URI.create(hdfs_addr), new Configuration());
    Path src = new Path(hdfs_addr+"/ww/ff");
  
    try{
      FileOutputStream outputStream=new FileOutputStream("D:\\c.txt");
      FSDataInputStream inputStream=fileSystem.open(src);
   IOUtils.copyBytes(inputStream, outputStream, 4096, false);
  } catch (Exception e) {
   // TODO: handle exception
   e.printStackTrace();
  }
    
  }
}

列表

下发源文件

删除文件

下发文件

结束

OVO

算法设计与分析报告5 贪心算法

本文发布地址(方便阅读):

  1. https://cmd.dayi.ink/WfnxTsYRQ4OdwI587BGDRQ
  2. https://blog.dayi.ink/?p=89
  3. https://www.cnblogs.com/rabbit-dayi/p/17817387.html
  4. https://type.dayiyi.top

1. 硬币找零问题

贪心

就是假设我们是收银员,需要找零,然后需要选取最少的硬币数量给他人。

我们直接从最大的依次给,给不了就给再小的,很爽。

但贪心的原理是子问题最优解推出整体问题最优解,也就是最优子结构,而对于子问题,只考虑当前怎么做最优,而不考虑整体情况,对于这个我们就只考虑现在需要的硬币而不考虑整体需要多少硬币。

实际的贪心问题需要证明,但是都贪心了,就贪心一点,不要那么多,直接做贪!

n = eval(input()) #要贪心的数额
arr = [10,5,1] # 面额
ans = 0
for i in arr:
  if n>=i:
    k = n//i #整除
    n -= i*k
    ans += k
    print(f"[info]{i} * {k}")

if ans ==0:
  print(-1)
else:print(ans)

  1. 最大面额的硬币比任何其他可能的硬币组合能表示的最大金额还要大。 这意味着任何较大金额的找零都应该首先尽可能多地使用最大面额的硬币
  2. 较小的硬币面额能被较大的硬币面额整除。
  3. 组合属性。 对于任意两个硬币面额ab,如果a > b,那么对于任何金额x,如果x能够用a来找零,那么x - b也能用a来找零。移除一个较小面额的硬币并不会改变剩余金额能否用较大面额的硬币找零。也就是说,x可以被a整除或者x大于a,那么从x中减去b(得到的金额是x-b)仍然能够使用面额为a的硬币找零。

比如这道题:

https://www.luogu.com.cn/problem/B3635

如果我们需要15元,我们的贪心算法会这样找:

15
15 - 1*11
4 - 4*1

这样就需要5枚硬币,而这里,我们则只需要3枚硬币(3*5)。

一般这两种情况会导致:

  1. 硬币的面额不能互相组合出更小的面额中的任何一个。
  2. 较小面额的硬币不能组合成较大面额的硬币。

对于本题中的硬币系统,因为不能保证使用最大面额的硬币后,剩下的金额还能用较小的面额凑出,所以这里不能用贪心算法。

那咋办嘛?

动态规划(Oh no)

  1. 定义状态:

    • dp[i] 凑成总金额 i 所需的最少硬币数量。

      假设我们想要凑成金额为6元,那么 dp[6] 将包含以下集合:

      • {1, 1, 1, 1, 1, 1}:使用六个1元硬币 1个硬币
      • {1, 5}:使用一个1元和一个5元硬币 2个硬币
  2. 状态初始化:

    • dp[0] = 0,因为凑成总金额0不需要任何硬币。
    • 其他状态初值可以设为无限,表示还没有找到凑成这个金额的方法。
  3. 状态转移方程:

    • 要凑成总金额 i,可以通过以下三种方式:

      • 用一个1元硬币加上金额为 i-1 的最优解
      • 用一个5元硬币加上金额为 i-5 的最优解
      • 用一个11元硬币加上金额为 i-11 的最优解
    • 因此,状态转移方程为 dp[i] = min(dp[i-1], dp[i-5], dp[i-11]) + 1
  4. 计算顺序:

    • 由小到大计算 dp[i],计算到 dp[n]
  5. 结果:

    • dp[n]
n = eval(input())
dp = [0x3f3f3f3f for i in range(n+1)]
dp[0]=0
for i in range(1,n+1):
  dp[i] = min(dp[i-1],dp[i-5],dp[i-11])+1
print(dp[n])

再来一道一样的题目题:

https://vjudge.net/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-T1781

n,m = map(int,input().split())
arr = list(map(int,input().split()))
dp = [0x3f3f3f3f for i in range(m+10)]
dp[0]=0
for i in range(1,m+1):
  for j in arr:
    if i>=j:
      dp[i] = min(dp[i-j]+1,dp[i])

if dp[m]==0x3f3f3f3f:
  print(-1)
else:
  print(dp[m])

..

AC:

2.活动安排问题

设有 n 个活动的集合 E={1,2,..,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动 i 都有一个要求使用该资源的起始时间 si 和一个结束时间 fi,且 si<fi。如果选择了活动 i ,则它在时间区间 [si,fi) 内占用资源。若区间[si,fi) 与区间 [sj,fj) 不相交,则称活动 i 与活动 j 是相容的。也就是说,当 fi≤sj 或 fj≤si 时,活动 i 与活动 j 相容。选择出由互相兼容的活动组成的最大集合。

这道题是纯贪心啦(DP也能做):

总是选择结束时间最早的活动,这样留给其它活动的时间就最多了,选择后使得对其他活动影响最小。(证明就不证了)

  1. 将所有活动按照结束时间进行排序。
  2. 选择结束时间最早的活动。
  3. 剔除所有与已选择活动时间上有冲突的活动。
  4. 重复步骤 2 和 3,直到没有剩余的活动为止。
# 时间复杂度 O(nlogn)(排序)
n = eval(input())
ls = [ ]
for i in range(n):
  st,end = map(int,input().split())
  ls.append((st,end))
ls.sort(key=lambda x:x[1])
# [(1, 3), (2, 5), (4, 6), (1, 7)]
# print(ls)
# vis = [0 for i in range(ls[-1][1]+10)]
now = 0
ans = 1 # 选了排序后的第一个
for i,v in enumerate(ls):
  print(v)
  # 如果起始时间大于5等于现在的终止时间(注意集合开闭)
  if v[0]>=ls[now][1]:
    now = i
    ans+=1
print(ans)

3.背包问题

  • 因为完全背包01背包都在之前的实验里有啦
  • 这里就拿这两种问题下的和课本样例输出下fi数组吧!

01 背包

n,c= 4,8
w = [0,2,4,5,3]
v = [0,5,4,6,2]
# 01背包
dp=[[0 for _ in range(c+10)]for i in range(n+10)]
for i in range(n+1):
  dp[i][0]=0

for i in range(1,n+1):
  for j in range(0,c+1):
    if j-w[i]<0:
      dp[i][j] = dp[i-1][j]
    else:
      dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

for i in range(0,n+1):
  for j in range(0,c+1):
    print(f"{dp[i][j]}",end=" ")
  print()
0 0 0 0 0 0 0 0 0 
0 0 5 5 5 5 5 5 5 
0 0 5 5 5 5 9 9 9 
0 0 5 5 5 6 9 11 11 
0 0 5 5 5 7 9 11 11 

回溯选择了什么:

# 回溯找出选中的物品
selected = []
i, j = n,c
while i>0 and j > 0:
  if dp[i][j] != dp[i-1][j]:
    selected.append(i)
    j -= w[i]
  i -= 1
selected.reverse()  # 因为是逆向查找的
for item in selected:
    print(f"Sel:{item} weight:{w[item]} value:{v[item]}")

贪心?

我觉得是不对的啦

至少不一定可以求出最优解,贪心算法在每一步都选取当前最优的选择,但是对于01背包问题,当前最优的选择不一定能导致全局最优解。

就比如这样,假设背包的容量为10,有以下三件物品:

  • 物品A:重量3,价值5
  • 物品B:重量4,价值6
  • 物品C:重量7,价值10

如果使用贪心算法根据单位重量价值(价值除以重量)来选择物品,我们将会选择物品A(单位重量价值为1.67)和物品B(单位重量价值为1.5),总重量为7,总价值为11。
但是,最优解是选择物品B和物品C,总重量为11(如果背包可以装11的话),总价值为16。

但是课本例题的数据如果用这种贪心似乎还能跟DP选的一样,但这不能全部情况啦

n,c= 4,8

w = [0,2,4,5,3]
v = [0,5,4,6,2]
# 贪心

v_old = -1.00
ans_val = 0
left_c =  c
for i in range(1,n+1):
  v_now = v[i]/w[i]
  if v_now>v_old and left_c>=w[i]:
    ans_val+=v[i]
    left_c-=w[i]
    print(f"Sel:{i} weight:{w[i]} value:{v[i]} attempt:{v_now}")
  v_old = v_now

print(ans_val)

输出结果,虽然跟01 DP一样,但是这个题目正确不能说明对于全部正确。

Sel:1 weight:2 value:5 attempt:2.5
Sel:3 weight:5 value:6 attempt:1.2
11

比如这样一组数据就没法正常贪心成功:

所以贪心不能代表全部,也经常不能得出正确解(不如说得出正确解是巧合)

完全背包

假设背包容量还是这个情况(C=8),但是我们的物品有无限个。

这里数据比较小,没有用递推优化DP

# 完全背包
dp=[[0 for _ in range(c+10)]for i in range(n+10)]
for i in range(n+1):
  dp[i][0]=0

for i in range(1,n+1):
  for j in range(0,c+1):
    for k in range(0,int(j/w[i])+1,1):
      dp[i][j] = max(dp[i-1][j-k*w[i]]+v[i]*k,dp[i][j])

for i in range(0,n+1):
  for j in range(0,c+1):
    print(f"{dp[i][j]}",end=" ")
  print()

0 0 0 0 0 0 0 0 0 
0 0 5 5 10 10 15 15 20 
0 0 5 5 10 10 15 15 20 
0 0 5 5 10 10 15 15 20 
0 0 5 5 10 10 15 15 20 

算法实验报告1

发布地址(方便阅读):

  1. https://cmd.dayi.ink/3VqGmm4dRamR85T2ptXCsQ
  2. https://blog.dayi.ink/?p=91

T1

N = eval(input())
nums = [i for i in range(1, N + 1)]
res = []
def fn(n, st, cur):
  if n < 0:
      return
  if n == 0:
      res.append(cur)
      return
  for i in range(st, len(nums)):
      fn(n - nums[i], i, cur + [nums[i]])
fn(N, 0, [])
print(res[1:len(res)-1])

T2

ls,k = eval(input())
st = sorted(ls)
print(st[k-1])

T3

ls = eval(input())

def calc(len_):
  res = []
  cmax = -0x3f3f3f3f
  for i in range(1,len(ls)):
    l = i-1
    r = l+len_
    if r>len(ls):
      break
    tmp_ls =ls[l:r]
    print(tmp_ls)
    tmp_sum = sum(tmp_ls)
    if tmp_sum>=cmax:
      res = tmp_ls
      cmax = tmp_sum
  return res

print(calc(2))

T4

有n名选手参加一个进行n-1天的比赛。每一名选手都需要和其他n-1名选手进行一场比赛,且每位选手每天只进行一场比赛。请为比赛安排日程。输入n,输出一个二维数组,令第i行、第j列的值代表第个选手在第j天的比赛。
#include<bits/stdc++.h>
int N;

struct node{
  int whoami;
};
int mp[1024][1024];

inline void debug_print(){
  for(int i=1;i<=16;++i){
    for(int j=1;j<=16;++j){
      std::cout<<mp[i][j]<<" ";
    }
    std::cout<<"\n";
  }std::cout<<"\n";
}
inline void solve(int sz){
  if(sz==2){
    mp[1][1]=1;
    mp[1][2]=2;
    mp[2][1]=2;
    mp[2][2]=1;
    return;
  } 
  solve(sz/2);
  //复制当前数据到右下角
  for(int i=1;i<=sz/2;++i){
    for(int j=1;j<=sz/2;++j){
      mp[i+sz/2][j+sz/2]=mp[i][j];
    }
  }
  //扩展左上角和左下角
  for(int i=1;i<=sz/2;++i){
    for(int j=1;j<=sz/2;++j){
      mp[i][j+sz/2]=mp[i][j]+sz/2;
      mp[i+sz/2][j]=mp[i][j]+sz/2;
    }
  }
} 

inline void print_res(int n){
  using namespace std;
  cout<<"   ";
  for(int i=1;i<=n-1;++i){
    cout<<"D"<<i<<"  ";
  }
  cout<<"\n";
  for(int i=1;i<=N;++i){
    for(int j=1;j<=n;++j){
      if(mp[i][j] > N) cout<<"R   "; // 只有当值大于N时才打印'R'
      else cout<<mp[i][j]<<"   ";
    }
    cout<<"\n";
  }
}

int main(){
  using namespace std;
  // N=8;
  std::cin>>N;
  int n = N;
  if((n & (n - 1))!=0){
    n = pow(2, ceil(log2(n)));
    // printf("xxx:%d",n);
  }
  solve(n);
  // debug_print();
  print_res(n);
}

输出结果:

=========2==========
   D1  
1   2   
2   1   
=====================

=========3==========
   D1  D2  D3  
1   2   3   R   
2   1   R   3   
3   R   1   2   
=====================

=========4==========
   D1  D2  D3  
1   2   3   4   
2   1   4   3   
3   4   1   2   
4   3   2   1   
=====================

=========5==========
   D1  D2  D3  D4  D5  D6  D7  
1   2   3   4   5   R   R   R   
2   1   4   3   R   5   R   R   
3   4   1   2   R   R   5   R   
4   3   2   1   R   R   R   5   
5   R   R   R   1   2   3   4   
=====================

=========6==========
   D1  D2  D3  D4  D5  D6  D7  
1   2   3   4   5   6   R   R   
2   1   4   3   6   5   R   R   
3   4   1   2   R   R   5   6   
4   3   2   1   R   R   6   5   
5   6   R   R   1   2   3   4   
6   5   R   R   2   1   4   3   
=====================

=========7==========
   D1  D2  D3  D4  D5  D6  D7  
1   2   3   4   5   6   7   R   
2   1   4   3   6   5   R   7   
3   4   1   2   7   R   5   6   
4   3   2   1   R   7   6   5   
5   6   7   R   1   2   3   4   
6   5   R   7   2   1   4   3   
7   R   5   6   3   4   1   2   
=====================

=========8==========
   D1  D2  D3  D4  D5  D6  D7  
1   2   3   4   5   6   7   8   
2   1   4   3   6   5   8   7   
3   4   1   2   7   8   5   6   
4   3   2   1   8   7   6   5   
5   6   7   8   1   2   3   4   
6   5   8   7   2   1   4   3   
7   8   5   6   3   4   1   2   
8   7   6   5   4   3   2   1   
=====================

=========9==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   R   R   R   R   R   R   R   
2   1   4   3   6   5   8   7   R   9   R   R   R   R   R   R   
3   4   1   2   7   8   5   6   R   R   9   R   R   R   R   R   
4   3   2   1   8   7   6   5   R   R   R   9   R   R   R   R   
5   6   7   8   1   2   3   4   R   R   R   R   9   R   R   R   
6   5   8   7   2   1   4   3   R   R   R   R   R   9   R   R   
7   8   5   6   3   4   1   2   R   R   R   R   R   R   9   R   
8   7   6   5   4   3   2   1   R   R   R   R   R   R   R   9   
9   R   R   R   R   R   R   R   1   2   3   4   5   6   7   8   
=====================

=========10==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   R   R   R   R   R   R   
2   1   4   3   6   5   8   7   10   9   R   R   R   R   R   R   
3   4   1   2   7   8   5   6   R   R   9   10   R   R   R   R   
4   3   2   1   8   7   6   5   R   R   10   9   R   R   R   R   
5   6   7   8   1   2   3   4   R   R   R   R   9   10   R   R   
6   5   8   7   2   1   4   3   R   R   R   R   10   9   R   R   
7   8   5   6   3   4   1   2   R   R   R   R   R   R   9   10   
8   7   6   5   4   3   2   1   R   R   R   R   R   R   10   9   
9   10   R   R   R   R   R   R   1   2   3   4   5   6   7   8   
10   9   R   R   R   R   R   R   2   1   4   3   6   5   8   7   
=====================

=========11==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   R   R   R   R   R   
2   1   4   3   6   5   8   7   10   9   R   11   R   R   R   R   
3   4   1   2   7   8   5   6   11   R   9   10   R   R   R   R   
4   3   2   1   8   7   6   5   R   11   10   9   R   R   R   R   
5   6   7   8   1   2   3   4   R   R   R   R   9   10   11   R   
6   5   8   7   2   1   4   3   R   R   R   R   10   9   R   11   
7   8   5   6   3   4   1   2   R   R   R   R   11   R   9   10   
8   7   6   5   4   3   2   1   R   R   R   R   R   11   10   9   
9   10   11   R   R   R   R   R   1   2   3   4   5   6   7   8   
10   9   R   11   R   R   R   R   2   1   4   3   6   5   8   7   
11   R   9   10   R   R   R   R   3   4   1   2   7   8   5   6   
=====================

=========12==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   12   R   R   R   R   
2   1   4   3   6   5   8   7   10   9   12   11   R   R   R   R   
3   4   1   2   7   8   5   6   11   12   9   10   R   R   R   R   
4   3   2   1   8   7   6   5   12   11   10   9   R   R   R   R   
5   6   7   8   1   2   3   4   R   R   R   R   9   10   11   12   
6   5   8   7   2   1   4   3   R   R   R   R   10   9   12   11   
7   8   5   6   3   4   1   2   R   R   R   R   11   12   9   10   
8   7   6   5   4   3   2   1   R   R   R   R   12   11   10   9   
9   10   11   12   R   R   R   R   1   2   3   4   5   6   7   8   
10   9   12   11   R   R   R   R   2   1   4   3   6   5   8   7   
11   12   9   10   R   R   R   R   3   4   1   2   7   8   5   6   
12   11   10   9   R   R   R   R   4   3   2   1   8   7   6   5   
=====================

=========13==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   12   13   R   R   R   
2   1   4   3   6   5   8   7   10   9   12   11   R   13   R   R   
3   4   1   2   7   8   5   6   11   12   9   10   R   R   13   R   
4   3   2   1   8   7   6   5   12   11   10   9   R   R   R   13   
5   6   7   8   1   2   3   4   13   R   R   R   9   10   11   12   
6   5   8   7   2   1   4   3   R   13   R   R   10   9   12   11   
7   8   5   6   3   4   1   2   R   R   13   R   11   12   9   10   
8   7   6   5   4   3   2   1   R   R   R   13   12   11   10   9   
9   10   11   12   13   R   R   R   1   2   3   4   5   6   7   8   
10   9   12   11   R   13   R   R   2   1   4   3   6   5   8   7   
11   12   9   10   R   R   13   R   3   4   1   2   7   8   5   6   
12   11   10   9   R   R   R   13   4   3   2   1   8   7   6   5   
13   R   R   R   9   10   11   12   5   6   7   8   1   2   3   4   
=====================

=========14==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   12   13   14   R   R   
2   1   4   3   6   5   8   7   10   9   12   11   14   13   R   R   
3   4   1   2   7   8   5   6   11   12   9   10   R   R   13   14   
4   3   2   1   8   7   6   5   12   11   10   9   R   R   14   13   
5   6   7   8   1   2   3   4   13   14   R   R   9   10   11   12   
6   5   8   7   2   1   4   3   14   13   R   R   10   9   12   11   
7   8   5   6   3   4   1   2   R   R   13   14   11   12   9   10   
8   7   6   5   4   3   2   1   R   R   14   13   12   11   10   9   
9   10   11   12   13   14   R   R   1   2   3   4   5   6   7   8   
10   9   12   11   14   13   R   R   2   1   4   3   6   5   8   7   
11   12   9   10   R   R   13   14   3   4   1   2   7   8   5   6   
12   11   10   9   R   R   14   13   4   3   2   1   8   7   6   5   
13   14   R   R   9   10   11   12   5   6   7   8   1   2   3   4   
14   13   R   R   10   9   12   11   6   5   8   7   2   1   4   3   
=====================

=========15==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   R   
2   1   4   3   6   5   8   7   10   9   12   11   14   13   R   15   
3   4   1   2   7   8   5   6   11   12   9   10   15   R   13   14   
4   3   2   1   8   7   6   5   12   11   10   9   R   15   14   13   
5   6   7   8   1   2   3   4   13   14   15   R   9   10   11   12   
6   5   8   7   2   1   4   3   14   13   R   15   10   9   12   11   
7   8   5   6   3   4   1   2   15   R   13   14   11   12   9   10   
8   7   6   5   4   3   2   1   R   15   14   13   12   11   10   9   
9   10   11   12   13   14   15   R   1   2   3   4   5   6   7   8   
10   9   12   11   14   13   R   15   2   1   4   3   6   5   8   7   
11   12   9   10   15   R   13   14   3   4   1   2   7   8   5   6   
12   11   10   9   R   15   14   13   4   3   2   1   8   7   6   5   
13   14   15   R   9   10   11   12   5   6   7   8   1   2   3   4   
14   13   R   15   10   9   12   11   6   5   8   7   2   1   4   3   
15   R   13   14   11   12   9   10   7   8   5   6   3   4   1   2   
=====================

=========16==========
   D1  D2  D3  D4  D5  D6  D7  D8  D9  D10  D11  D12  D13  D14  D15  
1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   
2   1   4   3   6   5   8   7   10   9   12   11   14   13   16   15   
3   4   1   2   7   8   5   6   11   12   9   10   15   16   13   14   
4   3   2   1   8   7   6   5   12   11   10   9   16   15   14   13   
5   6   7   8   1   2   3   4   13   14   15   16   9   10   11   12   
6   5   8   7   2   1   4   3   14   13   16   15   10   9   12   11   
7   8   5   6   3   4   1   2   15   16   13   14   11   12   9   10   
8   7   6   5   4   3   2   1   16   15   14   13   12   11   10   9   
9   10   11   12   13   14   15   16   1   2   3   4   5   6   7   8   
10   9   12   11   14   13   16   15   2   1   4   3   6   5   8   7   
11   12   9   10   15   16   13   14   3   4   1   2   7   8   5   6   
12   11   10   9   16   15   14   13   4   3   2   1   8   7   6   5   
13   14   15   16   9   10   11   12   5   6   7   8   1   2   3   4   
14   13   16   15   10   9   12   11   6   5   8   7   2   1   4   3   
15   16   13   14   11   12   9   10   7   8   5   6   3   4   1   2   
16   15   14   13   12   11   10   9   8   7   6   5   4   3   2   1   
=====================

直接照着抄为python

import math

N = None
mp = [[0 for _ in range(1024)] for _ in range(1024)]

def debug_print():
    for i in range(1, 17):
        for j in range(1, 17):
            print(f"{mp[i][j]:2d}", end=" ")
        print()
    print()

def solve(sz):
    if sz == 2:
        mp[1][1] = 1
        mp[1][2] = 2
        mp[2][1] = 2
        mp[2][2] = 1
        return

    solve(sz // 2)
    # 复制当前数据到右下角
    for i in range(1, sz // 2 + 1):
        for j in range(1, sz // 2 + 1):
            mp[i + sz // 2][j + sz // 2] = mp[i][j]
    # 扩展左上角和左下角
    for i in range(1, sz // 2 + 1):
        for j in range(1, sz // 2 + 1):
            mp[i][j + sz // 2] = mp[i][j] + sz // 2
            mp[i + sz // 2][j] = mp[i][j] + sz // 2

def print_res(n):
    print("   ", end="")
    for i in range(1, n):
        print(f"D{i}  ", end="")
    print()
    for i in range(1, N + 1):
        for j in range(1, n + 1):
            if mp[i][j] > N:
                print("R   ", end="")
            else:
                print(f"{mp[i][j]:<4}", end="")
        print()

def init():
    global N
    n = N
    if (n & (n - 1)) != 0:
        n = 2 ** math.ceil(math.log2(n))

    solve(n)
    # debug_print()
    print_res(n)

if __name__ == "__main__":
    for i in range(2, 17):
        N = i
        print(f"========={i}==========")
        init()
        print("=====================")