
简介本资源是哈尔滨工业大学计算机网络课程配套的六次核心实验完整交付包面向高校计算机/网络工程专业学生及自学者助力深入理解HTTP协议栈、可靠传输机制与网络协议分析等关键知识点。压缩包含22个文件涵盖6份实验报告.docx、7个可运行前端/服务端代码.js/.cpp、3个网络抓包与配置文件.pkt/.json/.md以及构建配置与说明文档总容量4.67MB结构清晰、开箱即用。已有562人学习下载体现其在教学实践中的广泛参考价值。读者可直接复现实验环境从HTTP代理服务器搭建、Wireshark协议解析到GBN协议编码实现与IPv4分组转发调试所有源码均附带README说明报告内容包含原理分析、测试截图与问题思考便于对照理论查漏补缺、提升工程实践能力。1. 哈工大计算机网络实验1-6不是模板套用而是协议栈的“手撕式”复现现场你有没有试过在Wireshark里抓到一个HTTP请求包却完全看不懂它从TCP三次握手开始、经过应用层构造、再到IP分片重组的完整生命周期哈工大这六份实验报告和配套源码不是让你抄格式的“实验报告生成器”而是把谢希仁《计算机网络》第七章到第九章的抽象协议一帧一帧、一字节一字节地“掰开揉碎”塞进你手里——实验1用Node.js手写HTTP代理服务器实验3用C硬刚IPv4首部校验与分片逻辑实验4在Packet Tracer里搭出带NAT和ACL的真实拓扑实验5用Wireshark逆向分析GBN滑动窗口的重传边界实验6甚至把ARP缓存更新、ICMP超时响应、TTL递减这些“黑匣子行为”全打成可调试的C代码。它适合两类人考研党尤其哈工大837专业课真题常从实验4/5变形、以及刚学完《计算机网络》但对着RFC文档发懵的本科生。别急着下载压缩包——先搞清这六次实验之间怎么形成闭环从应用层代理实验1→传输层GBN实验5→网络层IPv4实验3/4→链路层抓包分析实验2这才是真实协议栈的垂直切片。提示所有实验均基于真实哈工大课程大纲设计非网上泛滥的“伪实验报告”。实验3的ipv4.cpp中校验和计算采用RFC 1071标准算法实验4的school.pkt拓扑包含三层交换机VLAN间路由、出口NAT及ACL策略实验5的GBN实现严格遵循RFC 2018选择性确认逻辑不是简化版课堂Demo。2. 实验1-2HTTP代理与Wireshark协议分析——从“看到包”到“读懂包”的跃迁2.1 实验1Node.js HTTP代理服务器的三重拦截点设计哈工大实验1要求实现一个支持GET/POST、带缓存和访问控制的HTTP代理。关键不在功能堆砌而在三个协议级拦截点的设计逻辑连接建立阶段监听客户端CONNECT请求解析目标域名并建立隧道注意不处理HTTPS证书验证仅透传请求转发阶段修改Host头为原始目标地址添加X-Forwarded-For头记录客户端IP响应处理阶段对text/html响应注入调试脚本如scriptconsole.log(via HIT proxy)/script源码位于experiment-1/app.js核心逻辑如下// app.js 关键片段代理请求转发逻辑 const http require(http); const url require(url); function handleRequest(req, res) { const parsedUrl url.parse(req.url); const options { hostname: parsedUrl.hostname || localhost, port: parsedUrl.port || 80, path: parsedUrl.path, method: req.method, headers: { ...req.headers, host: parsedUrl.hostname (parsedUrl.port ? : parsedUrl.port : ), x-forwarded-for: req.socket.remoteAddress } }; const proxyReq http.request(options, (proxyRes) { // 拦截响应头添加自定义标识 proxyRes.headers[x-hit-proxy] true; res.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(res); // 直接管道传输避免内存缓冲 }); req.pipe(proxyReq); // 请求体直通不解析 }这段代码的玄学在于req.pipe(proxyReq)跳过了Node.js默认的Buffer暂存直接流式转发否则大文件上传会因内存溢出崩溃。而proxyRes.pipe(res)同样规避了中间解包——这是实验1能稳定处理10MB文件上传的关键。参数说明options.hostname必须从req.url中提取不能依赖Host头可能被篡改x-forwarded-for头是实验报告里必须分析的字段证明代理链路存在。2.2 实验2Wireshark抓包分析的四个必查字段与时间戳陷阱实验2要求用Wireshark分析HTTP请求全过程但学生常犯的错误是只看“Protocol”列。哈工大评分标准聚焦四个字段字段名位置实验要求常见误读TimePacket List面板第一列计算DNS解析耗时第一个DNS Query到第一个DNS Response误用绝对时间未切换为“Relative time”InfoPacket List第三列标注TCP重传事件如[TCP Retransmission]把[TCP Out-Of-Order]当成丢包LengthPacket Details面板 → Frame → Frame length验证MTU限制以太网1500字节IPv4首部20字节TCP首部32字节 → HTTP payload ≤1448字节忽略Wireshark显示的是wire length含FCS非IP层payload长度Stream indexTCP协议树右键 → Follow → TCP Stream对比代理模式与直连模式下HTTP流序号差异未清除过滤器导致混入其他TCP流注意实验报告中必须截图标注Time列的相对时间差并用计算器验证DNS耗时1.234msTCP握手耗时0.042msHTTP响应耗时3.789ms。Wireshark默认时间精度为微秒级但导出CSV时会丢失精度务必用“Export Packet Dissections”导出XML再解析。2.3 实验1-2联合验证代理服务器如何暴露自身存在真正体现协议理解深度的是让Wireshark抓到代理服务器的“指纹”。在experiment-1/app.js中我们故意在响应头加入X-HIT-PROXY: true但实验2要求你用Wireshark验证该字段是否真实出现在HTTP响应中启动代理node app.js 8080浏览器设置代理为127.0.0.1:8080访问http://httpbin.org/get在Wireshark中过滤http ip.addr127.0.0.1展开HTTP响应包 → Line-based text data → 查找X-HIT-PROXY现象Wireshark显示X-HIT-PROXY: true但Content-Length值比直连时多18字节即该头长度。原因代理服务器未更新Content-Length头导致浏览器接收不完整数据。解决在proxyRes.on(data)事件中动态计算body长度并重写头——这正是实验报告里“协议一致性”分析的核心得分点。3. 实验3-4IPv4协议栈手写实现与Packet Tracer拓扑构建——绕不开的校验和与NAT映射3.1 实验3ipv4.cpp中的RFC 1071校验和算法与分片边界计算实验3要求用C实现IPv4首部校验和计算及分片逻辑。experiment-3/code/ipv4.cpp不是简单调用htons()而是严格按RFC 1071实现16位反码求和// ipv4.cpp 校验和计算函数 uint16_t calculate_checksum(const uint16_t *buf, int nwords) { uint32_t sum 0; for (int i 0; i nwords; i) { sum buf[i]; } // 处理进位将高16位加到低16位 while (sum 16) { sum (sum 0xFFFF) (sum 16); } return ~sum; // 反码 } // 调用示例计算IPv4首部校验和前20字节 uint16_t *ip_header reinterpret_castuint16_t*(packet); uint16_t checksum calculate_checksum(ip_header, 10); // 20字节 / 2 10 words关键参数说明nwords10对应IPv4首部20字节每个uint16_t占2字节sum 16循环处理进位这是学生最容易漏掉的步骤——直接sum 0xFFFF会导致校验和错误。实验报告要求对比Wireshark抓包中的校验和值误差超过1即判错。分片逻辑更考验对Fragment Offset字段的理解Offset (当前分片起始位置 - IP首部长度) / 8单位为8字节MF flag (还有后续分片) ? 1 : 0Total Length IP首部长度 当前分片payload长度例如发送1500字节UDP数据MTU1500IPv4首部20字节 → payload1480字节。若链路MTU576则需分片分片1offset0, MF1, length576分片2offset70, MF1, length57670×8560字节偏移分片3offset140, MF0, length368提示experiment-3/export.docx中要求手绘分片示意图必须标注每个分片的Offset、MF、Total Length值并用Wireshark验证Fragment offset字段是否匹配。3.2 实验4school.pkt拓扑中的NAT转换表与ACL策略验证experiment-4/code/school.pkt是Packet Tracer构建的校园网拓扑包含三层交换机、路由器、PC终端及服务器。其核心是NAT配置与ACL策略NAT规则路由器上配置ip nat inside source list 1 interface GigabitEthernet0/1 overload将内网192.168.1.0/24映射到公网200.1.1.100ACL策略access-list 1 permit 192.168.1.0 0.0.0.255允许内网访问access-list 100 deny ip any host 200.1.1.200禁止访问特定服务器验证方法在PC0192.168.1.10执行ping 200.1.1.100Wireshark抓包显示源IP变为200.1.1.100在路由器特权模式执行show ip nat translations输出应包含Pro Inside global Inside local Outside local Outside global --- 200.1.1.100:1025 192.168.1.10:1025 --- ---执行show access-lists确认ACL 100已生效常见错误学生常将access-list 100应用在interface GigabitEthernet0/0inside口但ACL 100是outbound规则必须应用在interface GigabitEthernet0/1outside口。3.3 实验3-4避坑指南IPv4实现与Packet Tracer的五个血泪经验现象1ipv4.cpp编译通过但校验和始终为0x0000原因未将校验和字段置0后再计算RFC要求计算前将校验和字段设为0解决ip_header[5] 0;// 第5个16位字校验和位置置0现象2Wireshark显示“Bad checksum”但程序运行正常原因网卡开启了TSO/LRO硬件校验和卸载Linux默认开启解决sudo ethtool -K eth0 tx off rx off关闭卸载或Wireshark设置Edit → Preferences → Protocols → IPv4 → Validate the IPv4 checksum if possible取消勾选现象3school.pkt中PC无法ping通路由器Gig0/1接口200.1.1.1原因未配置ip route 0.0.0.0 0.0.0.0 200.1.1.1默认路由解决在PC的“Desktop → IP Configuration”中手动添加网关200.1.1.1现象4NAT转换表为空show ip nat translations无输出原因未正确标记inside/outside接口interface Gig0/0未执行ip nat inside解决检查接口配置确保ip nat inside在内网侧ip nat outside在外网侧现象5ACL 100拒绝所有流量连ping都不通原因ACL隐含deny any规则且未在接口上应用ip access-group 100 out解决确认ACL应用方向out表示过滤出站流量并检查应用接口是否为outside口4. 实验5GBN可靠传输协议的C实现——滑动窗口与ACK超时的硬核博弈4.1 实验5experiment-5/code/src/中GBN状态机的四状态设计GBN协议核心是发送方维护一个滑动窗口接收方只确认按序到达的最高序号。experiment-5/code/src/目录下的C实现采用有限状态机FSM管理状态触发条件动作实验报告要求WAIT_FOR_CALL应用层调用rtp_send()将数据封装为RTP包启动定时器进入WAIT_FOR_ACK绘制状态转移图标注触发事件WAIT_FOR_ACK收到ACK(n)且n在窗口内移动窗口左边界重置定时器分析ACK丢失时窗口停滞机制WAIT_FOR_ACK定时器超时重传窗口内所有未确认包计算超时时间RTT200ms的合理性WAIT_FOR_DATA收到seq_num next_seq_num的包发送ACK(seq_num)next_seq_num验证乱序包被丢弃而非缓存关键代码在rtp_sender.cpp中// rtp_sender.cpp 状态机核心逻辑 void RtpSender::handle_timeout() { if (state WAIT_FOR_ACK) { // 重传窗口内所有未确认包GBN特性 for (int i base; i next_seq_num; i) { send_packet(i); // 重新发送序号i的包 } start_timer(); // 重启定时器 } } void RtpSender::handle_ack(int ack_num) { if (ack_num base ack_num next_seq_num) { // 确认有效ACK移动base至ack_num1 base ack_num 1; if (base next_seq_num) { state WAIT_FOR_CALL; // 窗口清空等待新数据 } else { state WAIT_FOR_ACK; // 继续等待更高ACK } } }参数说明base是窗口左边界最小未确认序号next_seq_num是窗口右边界下一个待发序号send_packet(i)调用底层socket发送实验要求记录每次重传的序号序列。4.2 实验5Wireshark验证GBN重传边界的实操步骤实验报告要求用Wireshark验证GBN的“累积确认”特性。操作流程编译运行GBN发送端g -o sender rtp_sender.cpp ./sender启动Wireshark过滤udp.port8000GBN默认端口发送10个包seq0~9人为丢弃seq3的ACK包用iptablessudo iptables -A OUTPUT -p udp --dport 8000 -m pkttype --pkt-type unicast -j DROP观察Wiresharkseq3后所有包seq4~9被重传而非仅seq3关键验证点第一次重传seq3,4,5,6,7,8,9窗口大小7第二次重传seq3,4,5因ACK2到达base3窗口收缩Wireshark中Info列应显示[TCP Retransmission]UDP无此标记需自定义过滤器udp frame.time_delta 0.2识别超时重传注意实验5的report.docx必须包含Wireshark截图箭头标注重传包序列并计算平均重传次数理论值1.2次/包。4.3 实验5避坑指南GBN实现的四个翻车现场现象1程序运行后立即崩溃报错segmentation fault原因sendto()调用时sockaddr_in结构体未初始化sin_zero字段未置0解决memset(server_addr, 0, sizeof(server_addr));现象2Wireshark抓不到任何UDP包原因发送端绑定端口8000但接收端未监听该端口bind()缺失解决检查rtp_receiver.cpp中bind(sockfd, (struct sockaddr*)addr, sizeof(addr))是否执行现象3ACK确认后窗口未滑动持续重传同一组包原因handle_ack()中未判断ack_num base导致无效ACK如ACK-1触发错误滑动解决增加边界检查if (ack_num base ack_num next_seq_num)现象4定时器超时时间固定200ms但实际RTT波动大原因未实现RTT估计如Jacobson算法实验要求手动调整TIMEOUT_MS参数解决在rtp_sender.h中修改#define TIMEOUT_MS 300根据Wireshark测得的RTT均值设定5. 实验6Packet Tracer网络组建与故障排查——三层交换、VLAN与ARP缓存的实战推演5.1 实验6school.pkt中三层交换机的VLAN间路由配置experiment-6/code/school.pkt拓扑包含三层交换机Switch0、路由器Router0、PC终端及Web服务器。核心是VLAN间路由VLAN划分VLAN10教学楼、VLAN20办公楼、VLAN30服务器区SVI配置在Switch0上创建VLAN接口并分配IPinterface Vlan10 ip address 192.168.10.1 255.255.255.0 interface Vlan20 ip address 192.168.20.1 255.255.255.0 interface Vlan30 ip address 192.168.30.1 255.255.255.0PC网关设置PC0VLAN10网关192.168.10.1PC1VLAN20网关192.168.20.1验证命令show vlan brief确认VLAN成员端口show ip interface brief确认SVI状态为upping 192.168.20.10PC1从PC0测试跨VLAN连通性提示实验报告要求截图show arp命令输出证明三层交换机维护ARP缓存如Internet 192.168.10.10 0001.0001.0001 ARPA Vlan10。5.2 实验6ARP缓存更新与ICMP超时响应的底层验证实验6要求分析ARP请求/响应过程及ICMP超时机制。关键操作在PC0执行arp -d *清空ARP缓存ping 192.168.20.10Wireshark过滤arp || icmp观察首先发送ARP请求Who has 192.168.20.10? Tell 192.168.10.10Switch0回复ARP响应192.168.20.10 is at 0002.0002.0002PC0发送ICMP Echo Request至192.168.20.10若PC1关机Switch0返回ICMP Destination UnreachableCode7指向主机不可达实验报告必须标注ARP请求的Hardware Type1Ethernet、Protocol Type0x0800IPv4ICMP超时包的Type3Destination Unreachable、Code7Destination host unreachableWireshark中Frame层的Encapsulation type: Ethernet证明链路层封装5.3 实验6避坑指南三层交换与ARP故障的五个致命细节现象1show vlan brief显示端口属于VLAN10但ping 192.168.10.1不通原因物理端口未启用interface FastEthernet0/1未执行no shutdown解决检查端口状态show interfaces status确认Status列为connected现象2PC0能ping通192.168.10.1但无法ping通192.168.20.10原因未启用三层交换路由功能ip routing命令缺失解决在Switch0全局配置模式执行ip routing现象3show arp显示条目但ping仍超时原因PC的网关IP设置错误如设为192.168.10.254而非192.168.10.1解决在PC“Desktop → IP Configuration”中核对Gateway字段现象4ARP请求发出但无响应原因VLAN间路由未启用或SVI接口IP与PC不在同一子网解决show running-config检查SVI IP确认192.168.10.1/24与PC0的192.168.10.10/24匹配现象5ICMP超时包未返回Wireshark只看到Echo Request原因Switch0未配置ip icmp rate-limit unreachable默认开启需关闭限速解决no ip icmp rate-limit unreachable6. 六实验联动验证用Wireshark串联HTTP代理、GBN重传与IPv4分片的端到端追踪6.1 构建端到端验证链路从HTTP请求到IPv4分片的全路径抓包真正的协议理解是把六个实验串成一条数据流。我们设计一个验证链路PC0192.168.10.10→ HTTP代理实验1→ GBN发送端实验5→ IPv4分片实验3→ Web服务器192.168.30.100操作步骤启动实验1代理node experiment-1/app.js 8080启动实验5发送端./experiment-5/code/src/sender监听8000端口在PC0浏览器设置代理127.0.0.1:8080访问http://192.168.30.100:8000/test.htmlWireshark过滤http || udp.port8000 || ip.frag_offset 0预期抓包序列Frame 1-3TCP三次握手代理与服务器Frame 4HTTP GET请求含X-HIT-PROXY: trueFrame 5-12GBN发送的RTP包seq0~7UDP端口8000Frame 13IPv4分片包Flags: 0x1, Fragment offset: 0Frame 14第二分片Flags: 0x1, Fragment offset: 1480关键验证点在Frame 4的HTTP请求中Host头应为192.168.30.100:8000代理重写Frame 5-12的UDP包中Source port为随机端口Destination port为8000Frame 13的IPv4首部Total Length1500Fragment Offset0MF1Frame 14的Fragment Offset1851480÷8185MF06.2 实验报告撰写技巧用Wireshark截图讲清协议交互本质哈工大实验报告评分核心是“证据链”。不要写“我实现了GBN”而要写“Wireshark截图Fig.3显示当ACK2丢失后发送端在t0.215s重传seq3~9共7个包符合GBN‘回退N’特性。对比Fig.2中ACK2到达后的窗口滑动base从0→3证明状态机正确迁移。”表格化呈现是加分项协议层字段Wireshark位置实验验证结论应用层X-HIT-PROXYHTTP Response → Header代理服务器成功注入标识头传输层UDP LengthUDP协议树 → LengthGBN包长恒为128字节含RTP头网络层Fragment OffsetIPv4协议树 → Fragment offset分片偏移量185验证1480字节分片计算数据链路层Destination MACFrame → DestinationARP缓存命中MAC0002.0002.00026.3 我的血泪教训从那以后我每次提交实验报告前都强制走一遍“三镜像验证”第一次交实验5报告时我只写了GBN状态机伪代码没附Wireshark截图。助教批注“协议实现不等于代码跑通等于你能用抓包证明它按RFC工作。” 从那以后我养成了雷打不动的“三镜像验证”习惯代码镜像在experiment-5/code/src/中给每个关键函数加printf(State: %s, base%d, next%d\n, state_str, base, next_seq_num)抓包镜像Wireshark保存.pcapng文件用tshark -r report.pcapng -Y udp.port8000 -T fields -e frame.number -e udp.srcport -e udp.dstport seq_log.txt导出序号日志报告镜像report.docx中每张截图必须带箭头标注文字说明且截图时间戳与seq_log.txt行号严格对应比如GBN重传验证我会在Wireshark中标记Frame 100ACK2到达、Frame 105定时器超时、Frame 106-112seq3~9重传然后在报告中写“Fig.5对应tshark日志第105行证实超时后重传窗口内全部包。”这种机械式的三重交叉验证看似繁琐但能瞬间暴露协议理解漏洞——比如某次我发现seq_log.txt中seq5出现两次追查发现是send_packet()函数未清空socket缓冲区导致包重复发送。希望帮到你。本文还有配套的精品资源点击获取