
简介华北电力大学计算机网络综合实验的完整报告与主要配置代码面向计算机网络课程学生、实验员及备考者覆盖网络设备认知、交换机/路由器基本配置、VLAN划分与VLAN间通信、OSPF/RIP/静态路由、NAT综合实验及协议分析等关键知识点。报告以实际组网为线索依次给出网络拓扑设计、IP地址规划、单臂路由与三层交换实现VLAN间路由、OSPF多区域cost调整观察、动态NAT/NAPT上网配置、TCP建连与释放报文抓包分析并附ACL安全过滤方法。编写过程记录问题与解决思路可直接用于实验复盘与报告撰写。压缩包内为1个doc文档21.91MB完整呈现实验任务书、步骤、拓扑图与代码配置已由154人学习下载适合需要系统掌握网络实验全流程、提升排错与设计能力的学习者。1. 计算机网络实验报告先想清楚这套实验到底在验证什么深夜机房Windows 上开 Wireshark过滤规则还没输完就看见一条 TCP RST 标记为红色。很多同学把这格截图放进实验报告注明“服务器拒绝了连接”。但老师会问RST 和 RST-ACK 的区别是什么标志位里是哪个 bit 为 1如果你只能回答“我用软件抓到了包”这份计算机网络实验报告就白写了。华北电力大学的计算机网络实验通常在真实本机网卡上完成重点不是配置路由器而是能把以太网帧、ARP、TCP 握手的字节级过程解释清楚。这套方案围绕报告主要代码展开适合正在写华电计算机网络实验报告、需要把协议栈落到可复现实验的人。2. 实验环境怎么选Wireshark Python 为什么比纯模拟器更适合写代码2.1 三种环境对比模拟器、虚拟机与本机协议栈做实验前先定环境这一步比想象中更重要。华电课内常用的载体有三种Cisco Packet Tracer、GNS3 虚拟机网络还有本机真实网卡加 Wireshark。Packet Tracer 的好处是可以拖拽交换机、路由器不需要硬件也能组网但它的协议实现是教学简化版很多报文头字段根本不暴露。GNS3 能加载真实设备镜像但配置命令会占掉大量时间你写完一套 RIP 配置可能已经没精力去逐字节分析报文。我更推荐第三种真实本机网卡的收发路径Wireshark 看帧Python 控制行为。这样你验证的是操作系统协议栈的真实行为不是模拟器里的参数展示。真实网络栈有个特点它会给你看“脏数据”。同一交换机下的 mDNS、SSDP 广播会混进来ARP 缓存命中之后不会再发请求TCP 收到数据后可能补上一个 ACK 而不是立刻回复。这些现象在模拟器里都不存在。做报告复盘时这些“脏数据”恰恰是老师判断你有没有亲手跑过的证据。纸上谈兵的代码通常只能给出和截图一致的结果回答不了“这个包为什么出现”或“这个包为什么不出现”。为了更直观比较我把三条路径放在一起环境报文真实性写主要代码的难度报告说服力Packet Tracer低字段省略不支持外部脚本中老师见得多GNS3 设备镜像较高协议完整需要通过模拟接口交互偏高环境搭建费时本机 Wireshark Python高包含真实网络现象直接写 Python socket/Scapy高也容易翻车选本机路径还有一个原因计算机网络实验的“主要代码”大多是协议栈之上的代码例如 TCP socket 通信、帧解析、IP 校验和验证。这类代码要求的是能对接到语言自带 socket API而不是思科命令行。用 Python 写能把注意力留在协议字段上而不是忙着兼容 C 的字节序和指针。理解抓包位置也很关键Wireshark 工作在数据链路层能看到完整的以太网帧socket 工作在传输层你写的代码只能观察到 TCP/UDP 已经处理好的数据。两层之间的差异正是实验报告要解释的核心。2.2 最小目录与依赖先能跑通再谈协议分析虽然华电不同老师给出的实验清单有差异但报告里“实验环境”这一节基本逃不掉。我一般会建一个最小目录把抓包文件、代码、报告分开避免交作业时把十几个临时脚本堆在桌面。mkdir -p ncepu-netlab/{pcap,codes,reports} cd ncepu-netlab python -m venv .venv source .venv/bin/activate # Windows 下改为 .venv\Scripts\activate pip install scapy这段命令做了四件事建目录、创建虚拟环境、激活环境、安装 Scapy。虚拟环境很重要实验室机房经常预装旧版 Scapy它在 Windows 下可能因为缺少 Npcap 驱动而无法发包新装虚拟环境能避开很多版本污染问题。代码文件我会命名为 eth_arp.py、tcp_srv.py、tcp_cli.py对应后面两类的实验。这样交报告时附录里的代码路径和说明能对上。依赖上只需要三样Python 3、Scapy、Wireshark/TShark。Scapy 用于发送构造帧和解析 pcapWireshark 用于人工核对TShark 放在验证阶段可以直接用命令行断言抓包结果。不要在报告里写“需要下载某版本”而要写清你实际跑通的命令和输出老师重点看的是你能否把环境复现出来。提示Windows 下 Scapy 发帧需要以管理员身份运行终端否则 raw socket 可能创建失败。这一点在报告里最好注明不然实验到一半会发现 ARP 发不出去。2.3 报告里必须写清的环境信息报告环境部分只写“Windows Wireshark”会被打回。老师需要看到可复现信息抓包接口名称、是否开启混杂模式、过滤表达式、抓包起止时间、本机 IP 与 MAC。这五个信息构成了一条完整实验线索。比如 ARP 实验你需要在报告里写明“在真实网卡上抓包混杂模式开启”否则无法解释为什么收到了发给其他机器的广播。有的同学习惯把 Wireshark 默认界面截图直接粘上去字段多、列宽乱老师根本找不到关键包。我通常会在抓包前清空界面再用过滤表达式把范围收窄截图只保留需要的列No、Time、Source、Destination、Protocol、Length、Info。在截图下面注明“过滤表达式为 arp ip.addr 192.168.1.1”这样任何人都能在同一环境复核。这里有个细节回环接口的特殊性。如果实验代码用 127.0.0.1 通信链路层没有以太网头部Wireshark 会把它当作 Null/Loopback 类型而不是 0x0800 的以太网帧。报告里写“以太网帧分析”就必须用真实网卡 IP而不是回环地址。为什么要在报告里写接口名因为 ARP 广播只在二层域生效。同一个实验室两台机器可能接到同一台交换机也可能接在不同 VLAN如果你写了接口名老师可以判断你的广播域范围。曾经有同学报告里贴了 ARP 广播包但没写自己机器在哪个网段结果解释不了为什么广播没有到达目标机器。环境信息不完全是格式要求它其实是你后续分析报文的逻辑基础。3. 以太网帧与 ARP用 Python 解析抓包文件把协议字段读成字节3.1 为什么从以太网帧开始帧格式决定了后面所有协议的位置计算机网络课里的分层模型很抽象但你从 pcap 文件真实读包时第一个字段就是目的 MAC第二个是源 MAC第三个是类型字段。这些固定字段是解码后面 IP 和 TCP 的起始点。0x0800 代表 IPv40x0806 代表 ARP0x86DD 是 IPv6。以太网帧还有一个容易被忽略的点最小长度是 64 字节不足时要补 padding数据不超过 1500 字节受 MTU 限制超过就要分片。这些约束在纯理论题里只会出现在选择题里但在抓包文件里会直接表现为长度字段异常。所以第一个实验最好直接落到以太网头上。你在 Wireshark 里看到的 Frame 信息实际上是抓包工具的容器头部包含时间戳和帧长度Ethernet II 部分才是真正的链路层。写代码解析时如果只用 socket 的 recv你会永远拿不到 MAC 头因为内核已经把链路层去掉了。想看到这一层必须用抓包文件或者用 Scapy 构造 raw frame。这也是“报告主要代码”里为什么要把本机抓包和代码结合起来的原因。3.2 解析 pcap 文件的代码把第一个文件读通抓包之后第一步是写代码读出以太网帧。下面的代码读取 pcap 文件打印前 30 个包的基本字段。我用这种方式来验证抓包文件没抓错也用来生成报告里需要的材料。from scapy.all import rdpcap, Ether, ARP, IP, TCP packets rdpcap(pcap/eth_arp.pcap) for i, pkt in enumerate(packets[:30]): if Ether in pkt: eth pkt[Ether] mac_dst, mac_src eth.dst, eth.src eth_type eth.type line f[{i}] {mac_dst} - {mac_src} type0x{eth_type:04x} if ARP in pkt: arp pkt[ARP] line f arp_op{arp.op} {arp.psrc} - {arp.pdst} elif IP in pkt: line f ip{pkt[IP].src} - {pkt[IP].dst} print(line)逻辑说明rdpcap 会把整个 pcap 文件读进内存适合课时作业这种小文件如果文件特别大建议换成 PcapReader 循环读取避免内存峰值。Ether in pkt判断链路层是否是以太网帧以太网类型字段是网络字节序所以eth.type是一个大端整数直接打印 0x0800、0x0806 等值。ARP 报文有 op 字段1 是 request2 是 replyarp.psrc和arp.pdst是 IPv4 地址hwsrc和hwdst是 MAC 地址。参数说明[:30]是 Python 列表切片只取前 30 个包避免报告截图太长。pcap 路径用相对路径pcap/eth_arp.pcap配合第 2 章构建的目录从项目根目录运行时不会找不到文件。如果你抓回的文件来自 Linux cooked capture链路层不是 Ether这段代码会全部跳过。这是常见差异后面避坑章会再说。3.3 自己发一次 ARP 请求并抓到它如果直接 ping 网关ARP 缓存命中后不会触发广播。最可控的方式是用 Scapy 手工构造 ARP 请求同时开着 Wireshark 抓包。这样你能确定请求包是这一刻产生的并且可以在报告里标注“人为触发”。from scapy.all import Ether, ARP, srp, conf conf.verb 0 req Ether(dstff:ff:ff:ff:ff:ff) / ARP( op1, hwsrc00:11:22:33:44:55, psrc192.168.1.100, hwdst00:00:00:00:00:00, pdst192.168.1.1 ) ans, _ srp(req, ifaceeth0, timeout3) for sent, recv in ans: arp recv[ARP] print(reply from, arp.psrc, mac, arp.hwsrc)代码逻辑Ether(dstff:ff:ff:ff:ff:ff)构造广播帧保证请求能送到同一二层域的所有机器。ARP op1 表示请求hwdst填零表示“目标 MAC 未知”。srp在第 2 层发送并等待响应timeout3 表示最多等 3 秒。参数说明hwsrc 必须填本机真实 MAC否则协议栈可能把收到的响应当作无效包直接丢弃psrc 要填本机局域网 IP不能用 127.0.0.1。iface 参数是重点Linux 下通常是 eth0 或 ens33Windows 下需要到 Wireshark 接口列表里看可能是“以太网”或“WLAN”。网上代码多写 eth0直接抄过来在 Windows 上大概率报错。如果收不到任何回复先查 ARP 缓存是否命中再确认目标 IP 是不是确实在线。3.4 报告里最该写清楚的三个字段很多同学把整张 Wireshark 列表截图放上去字段一堆解释却很空。老师真正想看到的是三个字段目的 MAC、源 MAC、类型字段。写报告时我会用一个小表把每个字段的值和含义写清楚。例如目的 MAC 是ff:ff:ff:ff:ff:ff要解释这是广播地址对应 ARP 请求需要发送到同一广播域内所有主机源 MAC 是本机真实网卡地址type0x0806 对应 ARP。第三个容易忽略的是 ARP 报文的 op 字段。请求 op1回复 op2很多同学只截广播包不截回复结果看不到完整的“一问一答”。报告里应当把请求和回复两张图并列标注它们是一对并指出回复是单播还是广播。这样就能解释为什么目标主机会回一个单播帧而不是再广播回去。帧尾部还有一个 FCS 字段是 CRC-32 校验值Wireshark 默认不展开。如果你想在报告里讨论坏帧可以在以太网选项里打开 FCS 后缀但多数基础实验不需要别硬写。4. TCP Socket用三次握手的状态机换一道“看得见”的代码4.1 为什么 TCP 实验要写在应用层而不是配置命令TCP 实验如果只看报文体会不深。最好用 socket API 写一次完整通信因为 connect()、accept()、send()、close() 这些函数正好命中 TCP 状态机。connect() 返回表示三次握手已完成accept() 返回表示服务器已经进入 ESTABLISHEDclose() 触发四次挥手。如果你只用抓包工具看别人的报文或者只配置路由命令代码部分就无法交付标题里的“主要代码”也就落空了。socket API 的抽象程度适合做状态实验但要注意socket 层看不到 MSS 协商、窗口缩放、重复 ACK 等细节。这些内容在传输层头部里不写抓包代码是看不出来的。所以我的做法是“代码控制状态抓包验证字段”两边对得上才写进报告。这比单独跑一段 hello world 或者单独抓包更能说明问题。4.2 最小服务端和客户端代码以回环地址为例先给可以跑通的最小服务端代码。端口选 12345避免占用 80、443 这类常用端口也方便抓包过滤。# tcp_srv.py import socket import time srv socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind((127.0.0.1, 12345)) srv.listen(5) print(waiting for connection...) conn, addr srv.accept() print(accept from, addr) data conn.recv(4096) print(received:, data.decode(utf-8, errorsignore)) conn.sendall(bhello from server) time.sleep(0.5) conn.close() srv.close()再看客户端# tcp_cli.py import socket cli socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.connect((127.0.0.1, 12345)) cli.sendall(bping) resp cli.recv(4096) print(server said:, resp) cli.close()逻辑说明server 端一次只处理一个连接这是实验代码刻意保持的最小并行度。connect()返回时内核已经完成 SYN、SYN-ACK、ACK 的交互你在 Wireshark 里看到的三个报文都在 connect 返回之前发生。server 端的accept()返回时连接也已经建立完成。注意第三次握手的 ACK 到达 server 后server 内核才会把它移入 accept 队列这个顺序在报告里可以画成时间线。client 的close()会主动发送 FIN触发四次挥手server 端time.sleep(0.5)是为了保证内核处理完客户端 FIN 之前程序还有时间正常 close不会变成 RST。参数说明SO_REUSEADDR让端口可以快速重用。但如果实验目标是观察 TIME_WAIT 状态就应当不设置它否则 2MSL 状态会被人为绕过。bind((127.0.0.1, 12345))表示只监听回环接口避免实验室局域网内其他机器连接如果要走真实以太网口抓包就改成(0.0.0.0, 12345)或本机局域网 IP同时把抓包接口也切到对应网卡。listen(5)里的 5 是 accept 队列长度不是最大连接数。recv(4096)是单次读取上限实际读到的字节数取决于内核缓冲区与网络分片不一定每次都是 4096这就是 TCP 粘包和拆包问题的起点也是老师很喜欢追问的地方。4.3 抓包过滤器与对应 TCP 头字段运行前在 Wireshark 上选好接口。只监听回环就选 LoopbackWindows 下通常是 “Adapter for loopback traffic”监听真实网卡就选对应以太网或 WLAN。显示过滤填tcp.port 12345。然后依次启动服务端和客户端每步之间隔一两秒便于观察状态推进。抓到的报文应该按下面的顺序出现阶段报文方向Flags 字段关键值第一次握手client - serverSYN1Seq 为客户端初始序列号ISN第二次握手server - clientSYN1, ACK1Seq 为服务端 ISNAck客户端 ISN1第三次握手client - serverACK1Ack服务端 ISN1数据传输client - serverPSH, ACK数据在 TCP payload 中四次挥手双向交替FIN, ACK各方向独立释放Wireshark 默认显示相对序号也就是第一次握手显示为 Seq0方便阅读。但答辩老师如果问“初始序列号是多少”你要能切到绝对序号。做法是在 TCP 详情面板里关掉 Relative sequence numbers或者用tcp.seq_raw字段。报告里最好同时保留两个视角相对序号用于解释状态推进绝对序号用于说明随机 ISN 的意义。还有一个典型错误把 ACK 的确认号理解成“已经收到了第 N 个字节”。实际上 ACK 中的确认号表示“期望对方下一个字节的序列号”。所以在第三次握手里Ack服务端 ISN1表示客户端期望收到服务端的第 ISN1 号字节也就是确认已收到 SYN 这个不占数据的序号。占不占数据是 TCP 报文分析里绕不过去的概念建议在报告里单独写一段说明。4.4 报告里的报文序列怎么把序号变化写进报告写报告时不要只贴三张截图。我一般会做一个表格列出每个包在 Wireshark 里的序号、方向、相对 Seq、绝对 Seq、Ack、Flags。这样老师不用重新打开你的 pcap 文件也能看到状态机是怎么推进的。表格里还要标注“该包是否携带数据”因为 SYN 和 FIN 本身占 1 个序号但不算应用数据。很多同学在这个地方出错导致计算下一段的 Seq 怎么都算不对。如果实验要求做 TCP 重传分析可以在抓包时人为制造丢包在客户端和服务端之间不做任何处理直接杀掉服务端进程然后观察客户端后续的 SYN 重传。这类截图比正常握手更有价值也更能体现你对超时重传机制的理解。不过注意不要为了制造重传把实验拖太长毕竟报告还要在截止时间前交。5. 计算机网络实验避坑5 个最容易让报告打回重写的现场避坑这部分是我最想写的。华电实验课环境差异很大有的机房是 Windows Npcap有的是 Linux 虚拟机还有远程桌面接回宿主机。环境不同踩的坑也不同。下面这五条是我两次被打回后总结出来的按出现的频率排。5.1 ARP 请求在 Wireshark 里总看不到现象构造好的 ARP 请求在 Scapy 里发送成功但 Wireshark 里只能看到回复包或者一个 ARP 请求都没有只有一堆 mDNS 广播。原因ARP 缓存命中了目标地址。操作系统在发送 IP 包前会查 ARP 缓存如果目标 IP 已经存在对应条目就不会再发广播请求而是直接封装单播帧发出。解决发 ARP 请求前清掉缓存。Windows 下执行arp -d *这条命令要写成arp -d *防止通配符被 shell 展开Linux 下执行ip neigh flush all。清缓存后再跑 Scapy 和 Wireshark就能看到完整的 request/reply 对。如果清了缓存还是看不到请求检查 iface 参数是否指向了错误接口。在 Windows 的真实网卡上接口名可能带中文不能直接抄 Linux 的 eth0。用scapy.all.get_if_list()打印本机接口列表对照 Wireshark 接口名选。5.2 bind 端口报 Address already in use现象第一次运行服务端正常第二次运行直接抛 OSError提示地址已被占用。原因上一次连接关闭后端口进入 TIME_WAIT 状态默认要等 2MSL 才能重新绑定。解决在 socket 创建后设置SO_REUSEADDR也就是代码里那行srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)。但这里要注意实验目的如果你想在报告里展示 TIME_WAIT 状态本身就别设这个选项先关闭连接然后在 Wireshark 里观察最后一次 ACK 与 FIN再在命令行用netstat -ano | findstr 12345查看端口状态。一旦设置了 REUSEADDRTIME_WAIT 可能被绕过报告里这部分就写不出来了。5.3 回环接口选错导致抓包为空现象代码监听 127.0.0.1Wireshark 也开了但抓到的包几乎没有或者只有几个无关的 UDP 包。原因回环流量只走 Loopback 接口不经过物理以太网网卡。你选的是“以太网”自然看不到 127.0.0.1 的 TCP 握手。解决把 Wireshark 捕获接口切到 LoopbackWindows 下是 “Npcap Loopback Adapter” 或 “Adapter for loopback traffic”Linux 下是 lo。另一种思路是把服务端 bind 改成0.0.0.0客户端连本机局域网 IP这样流量走真实网卡可以继续用以太网接口抓包。两种办法选一种写进报告不要两种混着写否则老师和你的记录对不上。5.4 程序一停就丢数据报告里 TCP 没挥手现象客户端收完服务器回复后立刻 close或者服务器 sendall 之后直接 close导致 Wireshark 里没有成对的 FIN/ACK反而看到 RST。原因数据还在内核缓冲区没被对端读走进程就关闭 socket内核认为连接异常发送 RST 而不是 FIN。解决在关闭连接前确保对端已经 recv 了数据。更稳的做法是调用shutdown(SHUT_WR)表示“我要发送的字节流结束了”这样仅关闭写半区对端还能继续回消息。四次挥手的两个方向是独立释放的用 shutdown 才能观察完整流程。实验代码里加一句cli.sendall(bping)和cli.shutdown(socket.SHUT_WR)是最直观的写法。5.5 抓包截图全是无关流量没法解释现象报告里的截图一大片SSDP、NBNS、mDNS就是找不到 TCP 握手。原因没设置显示过滤或者抓包前没有清空界面。解决抓包前复制一行tcp.port 12345到过滤栏回车后界面只显示关心的流量。截图时把 Time 列显示为从 0 秒开始的相对时间这样报告里写“第 0 秒 SYN第 0.001 秒 SYN-ACK”才有依据。另外别用默认的 Profile颜色区分在截图上不一定看得出来最好把关键包的 Flags 文本直接标出来。这不算技术问题但很多报告就是因为这条被扣了格式分。6. 进阶用 tshark 做断言把报告写成可复现的工程记录实验报告写完怎么知道自己有没有漏包我的习惯是用 tshark 做断言而不是只靠人眼截图。例如验证三次握手在 pcap 目录下执行tshark -r pcap/tcp_handshake.pcap -Y tcp.port 12345 -T fields -e tcp.seq_raw -e tcp.ack_raw -e tcp.flags.syn -e tcp.flags.ack | head -20这条命令把每个 TCP 包的关键字段抽出来head -20只看前 20 行。你应当看到第一行是0,0,1,0表示 SYN 置位、ACK 未置位第三行是1,1,0,1表示第三次握手的 ACK 置位。如果第一行就同时有 SYN 和 ACK说明客户端可能没抓到第一次握手原因是启动客户端时 Wireshark 还停在错误接口上。这类行级验证比截图可靠也方便写进报告的附录。参数说明-r读 pcap 文件-Y是显示过滤表达式和 Wireshark 语法一致-T fields指输出指定字段-e后面跟字段名。注意tcp.flags.syn输出 1 或 0表示标志位是否置位不是标志位本身的值。报告里要注明这一点。进阶一步把 tshark 输出接到 Python 里用 subprocess 调用检查前三行是否满足 SYN、SYN-ACK、ACK 的顺序。如果你能把这段断言脚本和结果写进实验报告老师一眼就能看出你理解了状态机的推进过程。有一点我一直后悔没早点做没有把绝对序号和相对序号同时保留。有一次答辩老师指着一张截图问初始序列号是多少我答不上来只能现场重新打开 Wireshark。后来我把每个关键包的 seq_raw 和 ack_raw 也导出到报告附录用相对序号讲流程用绝对序号回答细节。实验报告的本质不是展示工具多强而是让任何一个人照着你写的过滤器、代码和步骤能复现同一份报文序列。希望帮到你。本文还有配套的精品资源点击获取