
简介本资源是哈尔滨工业大学计算机网络课程配套的全套实验材料面向高校计算机及相关专业本科生覆盖网络协议原理理解、服务端开发与抓包分析等核心实践能力训练。内容完整包含6个经典实验HTTP代理服务器设计、HTTP分组收发与转发、GBN可靠传输协议实现、Wireshark协议分析、简单网络组建与配置每项均含详实实验报告docx与可运行源码js/cpp辅以README说明、配置文件json/.babelrc及网络拓扑pkt文件便于复现实验环境与调试验证。压缩包共22个文件以6份docx报告、7个js前端逻辑脚本、3个cpp协议实现代码为主另有md文档、json配置及pkt抓包文件总大小4.67MB结构清晰、开箱即用。已有563人学习下载适合课程预习复习、实验课参考、协议原理巩固及网络编程入门实践。1. 哈工大计算机网络实验1-6一套能跑通、能调试、能交作业的完整工程包你是不是也经历过老师刚布置完“用C实现GBN协议”手头只有一页伪代码和模糊的实验指导书Wireshark抓了一堆HTTP包却分不清哪个是代理转发、哪个是原始请求改了三遍ipv4.cppschool.pkt在Packet Tracer里死活不转发——最后发现只是子网掩码少写了个0这套哈工大计算机网络实验1-6的压缩包不是零散笔记也不是截图拼凑的PDF而是一套带可执行源码、配套抓包验证数据、含逐层注释报告、且全部通过本地环境实测运行的闭环资源。它覆盖从HTTP代理服务器实验1、分组收发与转发实验2–3、GBN可靠传输实验4、Wireshark协议深度分析实验5到Packet Tracer网络拓扑搭建实验6的全链路。适合正在啃计网实验、需要快速验证逻辑、或想对照标准实现查漏补缺的本科生与自学开发者——尤其当你卡在sendto()返回-1、recvfrom()阻塞超时、或.pkt文件加载后设备灯不亮时这份资源里的app.cpp编译日志、export.docx中的Wireshark过滤表达式、以及README.md里明确标注的GNS3/Packet Tracer版本兼容说明就是你翻车现场的后悔药。2. 实验1–3HTTP代理与分组收发——从app.js到ipv4.cpp的三层通信验证2.1 HTTP代理服务器Node.js实现与端口绑定陷阱实验1的核心是app.js非浏览器端JS而是Node.js服务端脚本它实现了基础HTTP代理功能接收客户端请求 → 解析Host头 → 转发至目标服务器 → 回传响应。关键不在“能转发”而在“能被Wireshark精准捕获”。常见错误是监听0.0.0.0:8080却未关闭系统自带的Web服务冲突导致EADDRINUSE。正确做法是显式指定本机IP并检查端口占用# 先查端口占用Linux/macOS lsof -i :8080 # 或 Windows netstat -ano | findstr :8080 # 启动时绑定具体IP如本机IPv4为192.168.1.100 node app.js --host 192.168.1.100 --port 8080提示app.js中http.createServer()的req.socket.remoteAddress必须打印到控制台这是后续Wireshark比对客户端真实IP的唯一依据若此处显示::1IPv6回环说明请求根本没走代理而是直连了本地服务。2.2 分组收发实验ipv4.cpp的原始套接字权限与ICMP校验实验2与实验3共用ipv4.cpp它用原始套接字Raw Socket构造并发送自定义IP数据包。这里踩坑率高达70%Linux下需sudo权限sudo ./a.out否则socket(AF_INET, SOCK_RAW, IPPROTO_RAW)直接返回-1Windows需启用SeCreateGlobalPrivilege通过ntrights.exe或组策略普通管理员权限不够更隐蔽的是ICMP校验和计算ipv4.cpp中checksum()函数对IP首部长度字段IHL的处理必须是header_length * 4而非直接取ip_header-ihl——因为该字段单位是4字节值为5表示20字节但代码里若误写ip_header-ihl * 5就会校验失败目标主机静默丢包。// ipv4.cpp 关键修正段原版易错点 uint16_t checksum(uint16_t *addr, int len) { uint32_t sum 0; while (len 1) { sum *addr; len - 2; } if (len 1) sum *(uint8_t*)addr; while (sum 16) sum (sum 0xFFFF) (sum 16); return (uint16_t)(~sum); } // 构造IP首部时IHL字段必须按规范设置 ip_header-ihl 5; // 表示首部20字节不可写成 ip_header-ihl 20; ip_header-tot_len htons(20 data_len); // 总长首部20数据长度2.3 分组转发实验双网卡配置与路由表干预实验3要求实现“转发”而非“发送”即本机作为中间节点透传数据包。这要求系统开启IP转发并手动添加路由规则。export.docx中给出的命令仅适用于Ubuntu 20.04新版内核需额外处理# 1. 开启IPv4转发临时 echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward # 2. 永久生效写入/etc/sysctl.conf echo net.ipv4.ip_forward 1 | sudo tee -a /etc/sysctl.conf sudo sysctl -p # 3. 关键添加策略路由避免回环 # 假设eth0接客户端192.168.1.0/24eth1接服务器10.0.0.0/24 sudo ip rule add from 192.168.1.0/24 table 100 sudo ip route add 10.0.0.0/24 via 10.0.0.1 dev eth1 table 100注意若跳过第3步ipv4.cpp发出的数据包会被本机路由表直接投递到lo接口Wireshark在eth0上抓不到转发流——这是实验3失败最隐蔽的原因。3. 实验4GBN协议实现——滑动窗口状态机与超时重传的硬核调试3.1 GBN核心逻辑发送方窗口与ACK确认的严格同步code/目录下的GBN实现gbn_sender.cpp与gbn_receiver.cpp采用经典状态机设计。其难点不在算法本身而在时间戳驱动的超时重传与ACK乱序到达的冲突处理。原版代码中sender_timeout_handler()存在一个致命缺陷当连续收到多个重复ACK如ACK2时若未清空已确认序列号队列会导致窗口左边界卡死新数据无法发送。修复方案是在每次处理ACK后强制推进窗口// gbn_sender.cpp 中 ACK处理逻辑修正 void handle_ack(int ack_seq) { if (ack_seq window_base ack_seq window_base WINDOW_SIZE) { // 清除已确认包的定时器 cancel_timer(ack_seq); // 关键推进窗口基线原版缺失此行 while (window_base ack_seq) { window_base; if (window_base ack_seq) break; } // 触发新数据发送 send_new_packets(); } }3.2 抓包验证Wireshark过滤表达式与序列号映射实验4要求用Wireshark验证GBN行为但原始export.docx中只写了tcp.port 8080这完全无效——GBN使用UDP自定义协议无TCP端口概念。必须基于UDP载荷内容过滤过滤目标Wireshark Display Filter说明所有GBN数据包udp.dstport 9999 udp.length 28实验约定目的端口9999且最小包含8字节头部20字节数据发送方重传包udp.dstport 9999 udp.payload[12:4] 01:00:00:00自定义头部第12–15字节为标志位0x01000000表示重传原版协议定义接收方ACK包udp.srcport 9999 udp.payload[8:4] 00:00:00:00第8–11字节为ACK类型标识0x00000000表示ACK血泪经验Wireshark默认不解析UDP载荷需右键UDP包 → “Decode As…” → 将端口9999强制设为“Raw”才能看到十六进制载荷否则payload[12:4]过滤永远为空。3.3 超时参数调优RTT估算与初始RTO设置GBN性能高度依赖超时重传时间RTO。原版gbn_sender.cpp将RTO硬编码为1000ms但在千兆局域网中这会导致过度重传。应改为基于RTT采样的动态RTO// 在 sender.cpp 中添加 RTT 采样逻辑 struct timespec start_time; clock_gettime(CLOCK_MONOTONIC, start_time); // 发送时记录时间戳存入包头部 packet.header.timestamp start_time.tv_sec * 1000000 start_time.tv_nsec / 1000; // 收到ACK时计算RTT struct timespec end_time; clock_gettime(CLOCK_MONOTONIC, end_time); long rtt_us (end_time.tv_sec - start_time.tv_sec) * 1000000 (end_time.tv_nsec - start_time.tv_nsec) / 1000; update_rto(rtt_us); // 使用RFC6298算法更新RTO4. 实验5Wireshark协议分析——从抓包到报文字段级解读的落地路径4.1 HTTP代理流量分离三元组过滤与会话追踪实验5要求分析代理场景下的HTTP交互但Wireshark默认将代理请求与目标服务器响应混在同一会话。必须用四元组源IP:端口 目标IP:端口精确隔离# 过滤代理服务器自身流量假设代理运行在192.168.1.100:8080 ip.addr 192.168.1.100 tcp.port 8080 # 过滤客户端到代理的请求客户端IP为192.168.1.50 ip.src 192.168.1.50 tcp.dstport 8080 # 过滤代理到目标服务器的请求目标为httpbin.orgIP假设为34.123.45.67 ip.src 192.168.1.100 ip.dst 34.123.45.67 tcp.dstport 80提示在report.docx中所有HTTP请求的Host头与GET路径必须与Wireshark中http.request.full_uri字段完全一致——这是验证代理是否正确解析并转发的关键证据。4.2 TCP三次握手与四次挥手的时序断点实验5强调“可靠连接建立与释放过程”但学生常把SYN、SYN-ACK、ACK当成独立事件。实际应关注时间轴上的微秒级间隔正常局域网中SYN→SYN-ACK延迟应1ms若10ms说明网络拥塞或代理中间件介入FIN-WAIT-1状态持续时间若60s表明对方未响应FIN可能进程崩溃或防火墙拦截export.docx中提供的tcp.analysis.flags过滤器如tcp.analysis.retransmission必须配合Statistics → Flow Graph使用才能可视化重传位置。4.3 避坑Wireshark常见问题与排查现象 → 原因 → 解决现象Wireshark抓不到任何HTTP包但浏览器能正常访问。原因代理设置错误如Chrome设置了系统代理但Firefox未设或app.js未监听正确IP。解决在浏览器地址栏输入http://127.0.0.1:8080/test.html直连代理同时Wireshark过滤http ip.addr 127.0.0.1。现象抓到大量TCP Retransmission但代理功能正常。原因Wireshark在高负载下丢包或网卡驱动未启用巨型帧Jumbo Frame。解决降低抓包缓冲区大小Edit → Preferences → Capture → Buffer size 2MB并禁用网卡节能模式。现象http.request.uri显示/但实际访问的是/api/data。原因HTTP/2协议下URI被HPACK压缩Wireshark默认不解析。解决强制浏览器使用HTTP/1.1Chrome启动参数加--unsafely-treat-insecure-origin-as-securehttp://127.0.0.1:8080 --user-data-dir/tmp/chrome-test --unsafely-allow-http-for-local-testing。5. 实验6Packet Tracer网络组建——school.pkt拓扑验证与故障注入技巧5.1 school.pkt拓扑结构与设备角色定义experiment-6/school.pkt构建了一个典型校园网模型核心层Router0运行OSPF连接各区域汇聚层Switch0VLAN 10教师办公区VLAN 20学生机房接入层PC0教师PCIP 192.168.10.10、PC1学生PCIP 192.168.20.10外联Router1模拟Internet配置静态路由指向Router0。关键验证点是跨VLAN通信PC0 ping PC1必须成功且Wireshark在Router0的G0/0接口应捕获到802.1Q标签帧VLAN ID10/20。5.2 故障注入模拟真实网络问题并定位README.md中隐藏了一个教学技巧通过手动制造故障训练排错能力。例如步骤1在Switch0上删除VLAN 20的SVI接口no interface vlan 20步骤2观察PC1的ping 192.168.10.10持续超时步骤3在Router0上执行show ip route发现无192.168.20.0/24路由步骤4在Switch0上恢复VLAN 20并配置interface vlan 20再show vlan brief确认PC1端口已加入。注意Packet Tracer 7.3.1以上版本中show running-config输出的VLAN配置必须包含switchport access vlan 20若缺失则PC1实际处于VLAN 1导致跨VLAN失败。5.3 配置同步避免Packet Tracer与GNS3的版本鸿沟school.pkt在Packet Tracer 7.2.1中可完美运行但若用GNS3 2.2.x导入会出现路由器无法启动问题。根本原因是IOS镜像不兼容Packet Tracer使用精简版IOSpt124-2.bin仅支持基础命令GNS3需完整IOS如c3640-a3jk9s-mz.124-25d.image且内存需≥192MB。解决方案在GNS3中新建路由器时选择c3640平台分配256MB RAM挂载完整IOS并在启动配置中禁用ip cefPacket Tracer不支持CEF加速。6. 从源码到报告一份实验资源的闭环验证方法论与我的强制习惯真正让这套资源区别于网上泛滥的“答案集”的是它内置的三层验证锚点源码可编译、抓包可复现、报告可溯源。我曾帮某高校实验室重构计网实验体系发现学生交的报告里90%的Wireshark截图来自百度图片而export.docx中每张图都带时间戳水印与过滤器文本框——这不是为了美观而是倒逼验证闭环。下面是我现在带学生必做的三步验证法已固化为checklist.md模板6.1 编译层验证确保源码在目标环境零报错不满足于g -o a.out *.cpp能运行必须检查符号表完整性nm a.out | grep U 输出为空U表示undefined symbol动态库依赖ldd a.out显示所有库路径有效尤其libpcap.so在Ubuntu 22.04需sudo apt install libpcap-dev内存安全用valgrind --leak-checkfull ./a.out运行10秒确认definitely lost: 0 bytes。6.2 抓包层验证Wireshark与源码日志的双向对齐这是最容易被忽略的环节。以实验1的app.js为例在代码中插入console.log([PROXY] ${new Date().toISOString()} ${req.method} ${req.url} → ${targetHost})Wireshark中导出HTTP流右键包 → Follow → TCP Stream保存为proxy_flow.txt用Python脚本比对时间戳与URL# validate_proxy.py import re with open(proxy_flow.txt) as f: flow f.read() urls re.findall(rGET\s(/.*?)\sHTTP, flow) # 与console.log中的URL列表逐行比对6.3 报告层验证文档结论必须有数据支撑report.docx中所有结论性语句如“GBN协议在丢包率15%时吞吐量下降42%”必须对应gbn_sender.cpp中stats.throughput变量的实时打印且该打印需在main()循环末尾强制刷新printf(Throughput: %.2f KB/s\n, stats.throughput); fflush(stdout); // 关键否则重定向到文件时内容延迟没有fflush()report.docx里的性能数据就是空中楼阁。从那以后我每次带学生做计网实验都强制走一遍这三步验证先make clean make看编译器脸色再开Wireshark抓包比对日志最后打开Word文档逐句核对结论来源。不是为了形式主义而是让学生亲手触摸到“理论→代码→信号→结论”的完整物理链路——当ipv4.cpp发出的字节流真正在网线里变成光信号当school.pkt里红灯变绿的瞬间抽象的协议才有了温度。希望帮到你。本文还有配套的精品资源点击获取