简介:这份广东工业大学计算机网络实验报告面向计算机、软件工程等专业学生,用于完成课程实验与期末报告撰写,帮助读者系统掌握网络配置与协议分析的基本技能。资源包内含1个doc文档,压缩包约1.73MB,内容按实验题目组织,涵盖Windows常用网络命令与协议分析软件基础两大模块。前者涉及Ping、IPconfig、Netsh、Tracert、Netstat、Arp、Nslookup等命令的测试与结果记录,并附问题讨论与故障排查思路;后者基于Wireshark抓包,分析Ethernet II封包、ARP请求与应答、IP及ICMP数据包格式,解析ping与tracert程序功能,还包含TCP三次握手过程与思考题解答。报告结构完整,含实验目的、内容要求、结果与讨论,可直接参考格式与分析方法。目前已有4029人学习下载,适合需要快速完成实验报告或复习网络基础操作的学生使用。
1. 广工计算机网络实验报告:从抓包到 socket,一份能跑通的复盘
广工的计算机网络实验,很多人第一次做的时候都以为只是「照着指导书敲命令、截图、写报告」。真正上手才发现,Wireshark 抓不到包、socket 连不上、ARP 表看不懂、报告里分析写不出东西,才是常态。这份实验报告的核心,不是把指导书抄一遍,而是把「协议到底怎么跑起来的」这件事,用抓包和代码验证一遍。它适合两类人:一类是正在做广工计网实验、想少走弯路的同学;另一类是想把谢希仁那本《计算机网络》里抽象概念落到实处的自学者。下面我按实验常见的几个模块,把原理、命令、参数和踩坑点讲清楚,你照着做,报告自然有东西写。
2. 实验环境搭建:Wireshark 抓包与 socket 编程的前置准备
2.1 为什么选 Wireshark + Python socket 这套组合
广工计网实验通常覆盖两类任务:一类是协议分析,用抓包工具看数据帧;另一类是网络编程,用 socket 实现客户端/服务端通信。抓包工具里 Wireshark 是最通用的,跨平台、过滤器强大、能直接看到每一层的头部字段。编程部分,C 和 Python 都能做,但 Python 的 socket 模块封装干净,几行代码就能跑通 TCP/UDP,适合把精力放在理解协议而不是内存管理上。
选型上有个现实考虑:实验机房的环境不一定让你装驱动或者改网络配置,Wireshark 的「捕获过滤器」和「显示过滤器」能帮你在不干扰网络的前提下只看自己关心的流量。Python 则不需要编译,改一行跑一次,调试成本低。如果你后续要做 HTTP 分析或者自定义协议,Python 的 struct 模块也能直接拼二进制包。
环境准备分三步:装 Wireshark、确认 Python 版本、选一个干净的实验网段。Wireshark 安装时注意勾选 Npcap(Windows)或者确保 libpcap 可用(Linux),否则抓不到任何接口。Python 建议 3.8 以上,socket 和 struct 都是标准库,不用额外装包。
2.2 抓包接口选择与过滤器配置
打开 Wireshark 第一件事不是点开始,而是选对接口。有线网卡、无线网卡、回环接口(lo / Loopback)是三个最常用的。做本机客户端-服务端通信实验时,如果服务端和客户端都在同一台机器,流量走的是回环接口,你抓物理网卡是抓不到的。这是第一个大坑,后面避坑章节会细说。
选好接口后,配置捕获过滤器。捕获过滤器用的是 BPF 语法,在抓包之前就过滤,减少数据量。常用写法:
# 只抓 TCP 且端口为 8080 的流量 tcp port 8080 # 只抓某个 IP 的流量 host 192.168.1.100 # 只抓 UDP udp # 组合:抓 192.168.1.100 和 192.168.1.101 之间的 TCP tcp and host 192.168.1.100 and host 192.168.1.101捕获过滤器填在 Wireshark 主界面顶部的输入框,点开始后生效。如果你不确定要抓什么,先不填,抓完再用显示过滤器筛。显示过滤器语法更灵活,比如tcp.port == 8080、ip.addr == 192.168.1.100、http.request.method == "GET"。两者的区别是:捕获过滤器在驱动层丢包,显示过滤器只是隐藏,包还在。
参数说明:tcp port 8080里的 port 不区分源端口和目的端口,只要有一端是 8080 就抓。host同理,源或目的匹配都算。如果你只想抓发往某个地址的包,用dst host,只想抓来自某个地址的用src host。
2.3 Python socket 最小可跑通示例
抓包之前,先让通信跑起来。下面是一个 TCP 服务端和客户端的完整示例,服务端监听 127.0.0.1:8080,客户端连上去发一条消息。
服务端代码:
import socket # 创建 TCP socket,AF_INET 表示 IPv4,SOCK_STREAM 表示 TCP server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置端口复用,避免重启时提示 Address already in use server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定地址和端口,空字符串表示监听所有网卡 server.bind(('127.0.0.1', 8080)) # 开始监听,参数 1 表示等待队列长度 server.listen(1) print('服务端已启动,等待连接...') # 接受连接,返回新的 socket 和客户端地址 conn, addr = server.accept() print(f'客户端 {addr} 已连接') # 接收数据,1024 是缓冲区大小 data = conn.recv(1024) print(f'收到: {data.decode()}') # 回复一条消息 conn.sendall('已收到你的消息'.encode()) # 关闭连接 conn.close() server.close()客户端代码:
import socket # 创建 TCP socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 连接服务端 client.connect(('127.0.0.1', 8080)) # 发送数据 client.sendall('Hello, 广工计网实验'.encode()) # 接收回复 response = client.recv(1024) print(f'服务端回复: {response.decode()}') # 关闭 client.close()逻辑说明:服务端先 bind 再 listen,accept 会阻塞直到有客户端连接。客户端 connect 触发三次握手,成功后 sendall 发数据。recv 也是阻塞的,直到收到数据或连接关闭。参数上,SO_REUSEADDR很重要,不加的话服务端重启时端口可能还被占用,报OSError: [Errno 98] Address already in use。listen(1)的 1 是 backlog,表示最多允许 1 个未处理的连接排队,实验够用,生产环境要调大。
跑通这两个脚本后,再开 Wireshark 抓回环接口,你就能看到完整的 TCP 三次握手、数据传输、四次挥手。报告里把抓到的包按帧展开,对照头部字段写分析,比干巴巴抄书强得多。
3. 协议分析实验:从 ARP 到 TCP 的抓包与字段解读
3.1 ARP 请求与应答的抓包验证
ARP 是很多实验的第一个抓包对象,因为它简单、触发快。在命令行先清空 ARP 缓存,再 ping 同一网段的另一台机器,Wireshark 里就能看到 ARP 请求和应答。
Windows 清缓存命令:
arp -d *Linux 清缓存命令:
sudo ip -s -s neigh flush all然后 ping 目标:
ping 192.168.1.101Wireshark 显示过滤器填arp,你会看到两类包:Opcode 为 1 的是请求(Who has 192.168.1.101? Tell 192.168.1.100),Opcode 为 2 的是应答(192.168.1.101 is at xx:xx:xx:xx:xx:xx)。展开 Ethernet II 头部看源 MAC 和目的 MAC,请求包的目的 MAC 是全 F 的广播地址,应答包是单播。
报告里要写清楚:ARP 请求为什么用广播、应答为什么用单播、ARP 缓存的作用和老化时间。这些在谢希仁书里有,但抓包看到实际字段后理解会深一层。注意,如果你 ping 的是外网地址,抓到的 ARP 是发给网关的,不是目标主机的,别写错。
3.2 TCP 三次握手与四次挥手的帧级分析
TCP 实验的核心是抓一次完整的连接建立和释放。用上面的 socket 代码,服务端先跑起来,Wireshark 开始抓包,然后跑客户端。显示过滤器填tcp.port == 8080。
三次握手对应三个包:
| 序号 | 方向 | 标志位 | 关键字段 |
|---|---|---|---|
| 1 | 客户端→服务端 | SYN=1, ACK=0 | Seq=0(相对),Win=64240 |
| 2 | 服务端→客户端 | SYN=1, ACK=1 | Seq=0, Ack=1 |
| 3 | 客户端→服务端 | ACK=1 | Seq=1, Ack=1 |
Wireshark 默认显示相对序号,方便看。展开 TCP 头部,重点看 Sequence Number、Acknowledgment Number、Flags、Window Size。三次握手的本质是双方交换初始序号并确认对方可达。
四次挥手对应四个包(有时合并成三个):FIN、ACK、FIN、ACK。主动关闭方发 FIN,进入 FIN_WAIT_1;被动方回 ACK,进入 CLOSE_WAIT;被动方处理完数据后发 FIN,进入 LAST_ACK;主动方回 ACK,进入 TIME_WAIT。TIME_WAIT 持续 2MSL,通常是 60 秒,报告里要解释为什么需要这个状态——保证最后一个 ACK 能到达,以及让旧连接的残留包在网络中消失。
抓包时如果只看到三次挥手,是因为被动方把 ACK 和 FIN 合并发了,这是正常的,不是抓包出错。
3.3 UDP 与 TCP 的对比抓包实验
UDP 实验通常用 DNS 查询或者自己写一个 UDP socket 来触发。DNS 查询走 UDP 53 端口,抓包过滤器填udp port 53,然后 nslookup 一个域名。
nslookup www.example.comWireshark 里能看到 DNS query 和 response,UDP 头部只有 8 字节:源端口、目的端口、长度、校验和。对比 TCP 头部最少 20 字节,UDP 没有序号、确认号、窗口、标志位,所以不可靠、无连接、开销小。
报告里做对比时,别只列表格,要结合抓到的包说:DNS 为什么用 UDP(查询短、重传成本低)、什么情况下用 TCP(响应超过 512 字节或区域传送)。这些细节能让分析部分有区分度。
4. Socket 编程实验:TCP 与 UDP 的代码实现与调试
4.1 TCP 并发服务端的实现方式
上面的单连接服务端只能处理一个客户端,实验里经常要求支持多客户端。两种常见做法:多线程和 select 多路复用。多线程写法简单,适合实验:
import socket import threading def handle_client(conn, addr): print(f'新连接: {addr}') try: while True: data = conn.recv(1024) if not data: break print(f'来自 {addr}: {data.decode()}') conn.sendall(f'已收到 {len(data)} 字节'.encode()) finally: conn.close() print(f'{addr} 已断开') server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(('0.0.0.0', 8080)) server.listen(5) print('并发服务端已启动') while True: conn, addr = server.accept() # 每个连接开一个线程处理 t = threading.Thread(target=handle_client, args=(conn, addr)) t.start()逻辑说明:主线程只负责 accept,每来一个连接就开一个新线程跑 handle_client。bind用0.0.0.0表示监听所有网卡,这样同一局域网的其他机器也能连。listen(5)的 backlog 调到 5,允许更多排队连接。参数上,recv(1024)的缓冲区大小可以调,但不要太小,否则大数据要多次接收。线程里用 try/finally 保证连接一定关闭,避免资源泄漏。
调试时如果客户端连不上,先检查服务端 bind 的地址。绑127.0.0.1的话只有本机能连,绑0.0.0.0才能被外部访问。防火墙也可能拦,实验时临时关掉或者放行端口。
4.2 UDP 服务端与客户端的关键差异
UDP 没有连接概念,服务端不用 listen 和 accept,直接 recvfrom 收数据,sendto 发数据。
UDP 服务端:
import socket server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(('0.0.0.0', 9090)) print('UDP 服务端已启动') while True: # recvfrom 返回数据和客户端地址 data, addr = server.recvfrom(1024) print(f'来自 {addr}: {data.decode()}') # sendto 需要指定目标地址 server.sendto(f'收到 {len(data)} 字节'.encode(), addr)UDP 客户端:
import socket client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP 的 connect 只是设置默认目标,不触发握手 client.connect(('127.0.0.1', 9090)) client.send('Hello UDP'.encode()) data, addr = client.recvfrom(1024) print(f'回复: {data.decode()}') client.close()关键差异:UDP 的connect不会发任何包,只是在内核里记录默认目标,之后可以用 send 而不是 sendto。UDP 不保证送达,实验里如果丢包,客户端 recvfrom 会一直阻塞,要加超时:
client.settimeout(3) # 3 秒超时参数说明:settimeout对 TCP 和 UDP 都适用,超时后抛socket.timeout异常,捕获后可以重发或退出。报告里写 UDP 分析时,要提到无连接、不可靠、无序,以及应用层怎么补偿(序号、确认、重传)。
4.3 用 struct 构造自定义协议包
进阶实验可能要求自定义一个二进制协议,比如头部 4 字节:2 字节魔数、1 字节类型、1 字节长度,后面跟负载。用 struct 打包和解包:
import struct # 打包:! 表示网络字节序,2s 表示 2 字节字符串,B 表示 1 字节无符号整数 magic = b'\xAB\xCD' msg_type = 1 length = 5 payload = b'hello' # 格式字符串:!2sBB5s packed = struct.pack('!2sBB5s', magic, msg_type, length, payload) print(f'打包后: {packed.hex()}') # 解包 unpacked = struct.unpack('!2sBB5s', packed) print(f'魔数: {unpacked[0].hex()}, 类型: {unpacked[1]}, 长度: {unpacked[2]}, 负载: {unpacked[3].decode()}')逻辑说明:!强制网络字节序(大端),保证跨平台一致。2s是固定长度字节串,B是 1 字节整数。打包后的字节可以直接用 socket sendall 发出去。解包时格式字符串必须和打包时一致,长度不对会抛struct.error。
参数上,如果负载长度不固定,可以用!2sBB先解头部,再根据 length 字段读剩余字节。这是很多二进制协议的标准做法,报告里可以画个头部结构图说明。
5. 实验报告避坑与常见问题排查
5.1 Wireshark 抓不到回环流量
现象:本机客户端连本机服务端,Wireshark 选了物理网卡,一个包都抓不到。
原因:本机通信走的是回环接口,流量不经过物理网卡。Windows 上回环接口叫Loopback或者Npcap Loopback Adapter,Linux 上是lo。
解决:在 Wireshark 接口列表里选回环接口。Windows 如果没看到,说明装 Npcap 时没勾选回环支持,重装 Npcap 并勾选。Linux 直接用sudo wireshark或者给 dumpcap 加权限。
5.2 服务端重启报 Address already in use
现象:服务端脚本跑完一次,再跑就报OSError: [Errno 98] Address already in use。
原因:TCP 连接关闭后,主动关闭方会进入 TIME_WAIT 状态,端口被占用约 60 秒。
解决:在 bind 之前加server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)。这行代码让内核允许重用处于 TIME_WAIT 的端口。注意,SO_REUSEADDR 和 SO_REUSEPORT 不同,前者是重用 TIME_WAIT,后者是多个 socket 绑同一端口,实验用前者就够。
5.3 抓包文件太大,Wireshark 卡死
现象:抓了几分钟,文件几百 MB,Wireshark 打开卡顿,过滤也慢。
原因:没设捕获过滤器,抓了大量无关流量,比如后台更新、其他设备的广播。
解决:抓包前先想清楚要抓什么,填捕获过滤器。如果已经抓了大文件,用tshark命令行过滤导出:
# 只保留 8080 端口的包,导出为新文件 tshark -r big.pcap -Y "tcp.port == 8080" -w filtered.pcap参数说明:-r读输入文件,-Y是显示过滤器,-w写输出文件。这样能把大文件缩小到只含关心的流量,再打开就流畅了。
5.4 socket 连接超时但 ping 得通
现象:ping 目标 IP 能通,但 socket connect 超时。
原因:目标机器防火墙拦了端口,或者服务端没监听在那个端口,或者绑的是 127.0.0.1 而不是 0.0.0.0。
解决:先在服务端机器上用netstat -an | grep 8080(Linux)或netstat -ano | findstr 8080(Windows)确认端口在监听,且监听地址是0.0.0.0:8080而不是127.0.0.1:8080。如果是防火墙,临时关掉或者加放行规则。实验环境里,Windows 防火墙默认拦入站连接,第一次跑服务端会弹提示,要选允许。
5.5 报告里协议分析写得太空
现象:抓包截图贴了一堆,但分析部分只会写「这是 SYN 包,用于建立连接」。
原因:没对照字段展开,没结合实验现象。
解决:每个关键包至少写清楚:谁发给谁、标志位含义、序号和确认号的变化、窗口大小、这个包在协议流程中的作用。比如三次握手的第二个包,要写「服务端回复 SYN+ACK,ACK=1 确认客户端的 SYN,SYN=1 请求建立反向连接,Seq=0 是服务端的初始序号」。这样写出来才有内容,也才能体现你真的看懂了。
6. 进阶技巧:用 tshark 批量分析抓包文件
实验报告如果要求分析多个抓包文件,或者要统计某种包的数量,手动开 Wireshark 一个个看效率太低。tshark 是 Wireshark 的命令行版本,适合批量处理和脚本化分析。
先确认 tshark 可用:
tshark -v如果提示找不到命令,Windows 下在 Wireshark 安装目录里,Linux 下装tshark包。
统计一个抓包文件里 TCP 三次握手的次数:
# 过滤 SYN 且不带 ACK 的包,就是第一次握手 tshark -r capture.pcap -Y "tcp.flags.syn == 1 and tcp.flags.ack == 0" | wc -l导出所有 HTTP 请求的 URL:
tshark -r capture.pcap -Y "http.request" -T fields -e http.host -e http.request.uri参数说明:-T fields指定输出字段模式,-e指定要输出的字段名。字段名可以在 Wireshark 里选中某个字段,状态栏会显示对应的过滤名。这个技巧在写报告时特别有用,比如要统计 DNS 查询的域名列表:
tshark -r capture.pcap -Y "dns.flags.response == 0" -T fields -e dns.qry.name还可以用-z参数做统计:
# 统计 TCP 会话 tshark -r capture.pcap -z conv,tcp # 统计协议分层 tshark -r capture.pcap -z io,phsconv,tcp会列出所有 TCP 会话的源地址、目的地址、包数、字节数,直接复制到报告里就是一张现成的会话表。io,phs是协议分层统计,能看到各层协议占比。
我自己的习惯是:抓包用 Wireshark 图形界面确认流程,分析用 tshark 批量跑数据,报告里的表格和统计数字都从 tshark 输出里来,避免手动数错。有一次实验要求统计 1000 个包的协议分布,手动翻页数了半小时还数错了,后来用tshark -z io,phs一条命令出结果,血泪经验。另外,tshark 的过滤语法和 Wireshark 显示过滤器完全一致,会一个就会另一个,不用额外学。
最后提醒一句:实验报告里的截图要清晰,关键字段用红框标出来,别截全屏然后让人自己找。分析文字要对着截图写,图和文能对上,报告才有说服力。希望帮到你。
本文还有配套的精品资源,点击获取