Files
NE_YuR/network/tcpquiclab/计算机网络实验指导手册.txt
2025-12-25 14:33:29 +08:00

327 lines
15 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

任务一头歌平台编程实现WEB服务器
任务二TCP 与 QUIC 协议性能对比分析
任务要求:
1. 基于 TCP 的客户端-服务器程序实现TCP服务器功能包括监听指定端口接受
客户端连接;接收客户端发送的消息;向客户端返回响应(包含接收数据的长
。客户端功能包括连接到TCP服务器向服务器发送指定消息接收服务器
响应并显示。
2. 基于QUIC的客户端-服务器程序实现使用quiche库实现QUIC服务器与客户端
能与第一条类似。
实验环境:
操作系统Windows或Linux
编程语言C语言其他语言也可能实现实验功能即可
依赖库socket库、quiche库
实验步骤:
1. 基于TCP的客户端-服务器程序实现
1环境配置
此处以Windows系统下使用VSCode运行c语言代码为例不同的系统、运行软件、
编程语言之间会有差异,自行决定选用工具,实现功能即可)。
在 Windows 系统中使用 VSCode 运行 C 语言代码之前,需要先配置 C 语言开
发环境。首先,在官网下载并安装 MinGW下载链接https://sourceforge.net/pr
ojects/mingw/)。安装完成后,需将 MinGW 的 bin 目录添加到系统的环境变量
Path 中,以确保能够在命令行中直接调用 gcc 等编译工具;
添加完成之后使用Windows+R命令打开cmd窗口运行命令gcc --version可验证是否成功安装。
在完成.c文件编写后必须编译并生成对应的.exe可执行文件才能启动调试过
程。
以上图中的hello.c为例其余代码的运行调试过程相同修改相应命令即可
首先在终端运行命令gcc hello.c -o hello.exe生成对应的hello.exe文件之后在对应
的路径下运行./hello.exe即可得到输出。
2代码书写
① 服务端代码
a. 引入相关头文件,链接 ws2_32.lib 库,对服务器监听的端口号和缓冲区大小
进行宏定义
定义需要用到的变量
使用Windows套接字编程首先需要初始化 Winsock 库。如果初始化失败,
打印错误信息,返回 -1 值,结束程序运行
使用socket()函数创建服务器套接字,如果创建失败,打印错误信息,清理
Winsock 资源并返回 -1 表示程序异常结束。
使用memset将 serverAddr 结构体清零,确保没有残留数据,设置地址族为
IPv4AF_INET绑定到所有可用的网络接口INADDR_ANY 表示接受任意IP 地址的连接),设置端口号,使用 htons() 函数确保端口号以网络字节序
大端传输。然后通过bind()绑定套接字,如果绑定失败将打印错误信息,
释放资源后结束程序运行。
使用listen()命令开始监听客户端连接,输出服务器正在监听的端口号。
等待客户端连接,输出客户端已连接的信息。
从客户端接收数据,存入 buffer 中,输出接收到的消息,向客户端返回响
应,包含接收到数据的长度。在通信完成后,关闭套接字,并清理资源。
② 客户端代码
a. 引入相关头文件,链接 ws2_32.lib 库,定义客户端连接的目标端口号,必须
与服务器端口一致。
b.
定义相关变量。
c.
初始化Winsock库确保在使用套接字之前初始化 Winsock。
d.
创建客户端套接字。设置地址族为
IPv4AF_INET设置目标服务器的端
口号,使用 htons() 转换为网络字节序。使用inet_addr() 将字符串格式的 IP
地址转换为 in_addr 结构体中可使用的二进制格式。此处使用的是本地回环
地址localhost意味着客户端将连接到本地运行的服务器。
连接到服务器。
和服务器进行通讯。
send() 函数将消息从客户端发送到服务器。参数 sock 是套接字message
是要发送的消息strlen(message) 是消息的长度0 表示没有使用附加标志。
recv() 函数从服务器接收数据,将其存储在 buffer 中。valread 存储实际接
收到的字节数。如果接收失败,返回值为负数,程序将打印错误信息。否则,打
印服务器的响应内容。
完成数据交换后,关闭套接字并清理 Winsock 库。
3实验结果示例
编写好.c文件后先在终端使用gcc命令生成.exe文件每次对代码进行改动后都
需要重新生成.exe文件gcc server.c -o server.exe -lws2_32其中-lws2_32表示链接
Winsock 库;生成并运行 server.exe 和 client.exe 后,可以看到以下实验结果。
4总结
本实验通过实现基于 TCP 协议的客户端-服务器通信,帮助理解网络编程的基本
原理。要求完成服务器端和客户端的代码编写,并通过实际运行验证通信功能。
2. 基于QUIC的客户端-服务器程序实现
1实验环境
本实验需要使用quiche库实现QUIC服务器与客户端除了要配置好VSCode的C语言
环境之外还需要安装quiche库确保它支持C语言的绑定。
安装quiche库的步骤如下
① 安装 Rust 和 Cargo
首先需要安装Rust开发环境Rust 包括了 cargo这是构建和管理 Rust
项目的工具。按照官网提供的下载地址和下载步骤下载Rust和cargohttps://rust-l
ang.org/zh-CN/tools/install/
② 克隆并构建quiche仓库
a. 使用git工具进行克隆这一步需要确保自己的主机安装了git工具如果没有
安装可以通过https://git-scm.com/install/windows下载安装使用Window
sR快捷键打开cmd窗口运行克隆命令
git clone https://github.com/cloudflare/quiche
cd quiche
如果上述方法遇到问题可以通过访问quiche库的github主页下载并解压其源
代码网址为https://github.com/cloudflare/quiche。
b. 准备好quiche仓库后在cmd窗口运行命令cargo build --release --features ffi构建
quiche的C语言接口注意这一步需要再下载好的quiche文件夹下完成
行这条命令没有报错后在quiche相应的文件夹下查找是否生成以下文件
Your local quiche Path\target\release\quiche.lib
Your local quiche Path\target\release\quiche.dll.lib
Your local quiche Path\target\release\libquiche.d
Your local quiche Path\target\release\libquiche.rlib
Your local quiche Path\quiche\include\quiche.h
确认存在就说明已经配置好quiche库的C语言静态库。
如果在构建quiche库的C语言接口时出现问题可以尝试检查以下问题
系统缺少 Visual Studio 或 Visual Studio Build Tools。访问https://visual
studio.microsoft.com/zh-hans/visual-cpp-build-tools/下载并安装Microsoft C
++生成工具,在安装过程中,确保选择了 C++ 构建工具(包括 Visual C
++ 编译器和链接器。安装完成之后找到编译工具链link.exe所在地
一般位于D:\Program Files (x86)\Visual Studio 2022\Build Tools\VC\Tool
s\MSVC
\14.44.35207\bin将bin文件地址添加到系统环境变量中。
未安装cmake工具。访问Cmake官网https://cmake.org/download/)下
载并安装适用于 Windows 的安装程序,选择 Windows x64 Installer。安装时确保勾选了 "Add CMake to the system PATH" 选项,这样可以在
命令行中直接使用 cmake。
安装完成后可以在终端检查是否成功安装。
未安装NASM编译器。访问官网https://www.nasm.us/)下载并安装适
合你系统的版本。安装后,将 NASM 的路径添加到 PATH 环境变量
中。在cmd窗口检验是否安装成功。
未安装clang编译器。可以参照这个博客下载并测试安装
https://blog.csdn.net/weixin_44565660/article/details/121758517
Clang安装后需要设置LIBCLANG_PATH环境变量指向libclang.dll的位
置。该文件通常位于Clang安装目录的bin文件夹下可以在该目录下找到这个
文件。检查该文件确实存在之后打开系统环境变量设置,在系统变量部分点
击新建然后添加一个新的环境变量,如下图所示。
之后验证通过运行命令echo %LIBCLANG_PATH%验证环境变量设置正确,
正确的话会返回Clang安装目录的路径。
③ 书写C语言代码熟悉quiche库的使用
a. VSCode运行环境
使用MinGW编译工具运行quiche库难度比较大不推荐新手使用因此
课程选用MSVC环境VS Build Tools运行C项目。打开“x64 Native Tools Command
Prompt for VS 2022”在窗口中cd到你的C工程目录然后输入code .启动VSCode。
b. VSCode配置文件
为了链接到quiche库需要改写相应C工程目录下.vscode的配置文件通过ar
gs命令指定静态库的位置。
c.
最小验证程序
新建verify_quiche.c先把quiche工具链跑通
#include <stdio.h>
#include <quiche.h>
int main(void) {
const char *v = quiche_version();
printf("quiche version: %s\n", v ? v : "(null)");
return 0;
}
使用cl命令生成相应的.exe文件
cl /nologo /Zi /EHsc /MD `
/I E:\quiche\quiche-master\quiche\include verify_quiche.c `
/Fe:verify_quiche.exe `
/link /LIBPATH:E:\quiche\quiche-master\target\release `
quiche.lib ws2_32.lib advapi32.lib `
crypt32.lib userenv.lib ntdll.lib
然后在VSCode终端运行该.exe文件输出quiche版本号就说明quiche的c语言
接口构建完成:
2代码书写
① 服务端代码
a. 准备quiche配置
b. 创建UDP socket并监听端口用socket(AF_INET/AF_INET6, SOCK_DGRAM, ...)创
建 UDP socketbind() 到指定端口(比如 5555设置成 non-blocking
样循环不会卡死在 recvfrom() 上,此时 server 已经在 “UDP 层”听包了,但
还没有 QUIC 连接对象
c. 进行主循环(核心框架)
主循环反复执行收UDP包。recvfrom()收到一个 QUIC UDP 包,同时拿到客
户端地址 peer_addr用于后续回包
d. 解析包头:收到 UDP 包后,先用 quiche_header_info() 解析 QUIC 头部,
拿到versionQUIC 版本dcid / scid连接 ID用于识别连接token
实验里可以不深入理解
e. 第一次收到合法包时,创建 QUIC 连接accept
f. 把 UDP 包交给 quiche 处理conn_recv
g. 如果连接已建立established就读 stream 并生成响应
h. 把 quiche 产生的所有 UDP 包发出去conn_send 循环)
② 客户端代码
a. 初始化 quiche_config
b. 创建 QUIC 连接 quiche_connect
c. 触发握手
d. recvfrom 后喂给 quichequiche_conn_recv
e. 建立连接后quiche_conn_is_established(conn))发送一次消息
f. 调用quiche_conn_readable(conn) 函数获取可读 stream对每个 stream id
调 quiche_conn_stream_recv打印响应并设置 got_resp = true
g. 每轮循环 flush_egress否则ACK / handshake / stream data 都可能“卡在内存
里没发出去”,表现为建立慢或收不到响应
h. timeout 处理
i.
收到响应后关闭连接
③ 运行代码
首先需要在终端使用openssl命令生成证书否则不能编译通过
生成证书之后使用cl命令得到相应的.exe文件cl命令参考
cl /nologo /Zi /EHsc /MD `
/I E:\quiche\quiche-master\quiche\include quic_server.c
`
/Fe:quic_server.exe
`
/link /LIBPATH:E:\quiche\quiche-master\target\release `
quiche.lib ws2_32.lib advapi32.lib crypt32.lib userenv.lib ntdll.lib
3实验结果示例
运行生成的.exe文件得到结果如下
任务三对比分析TCP与QUIC性能
任务 3.1:连接建立时间对比
任务要求:
1. 测量 TCP 三次握手时间:使用 Wireshark 捕获 TCP 连接建立过程;记录从客户
端发送 SYN 到收到服务器 ACK 的时间。
2. 测量 QUIC 连接建立时间:使用 Wireshark 捕获 QUIC 连接建立过程;记录从客
户端发送初始数据包到完成握手的时间。
3. 对比分析:记录 3 次测试的平均值,比较两种协议的连接建立效率
实验环境:
安装好wireshark软件即可
实验步骤:
1. 打开wireshark主界面之后根据书写的代码选择正确的网卡之后开始捕获
2. 根据代码端口或者协议类型设置wireshark的显示过滤器
3. 运行书写的代码模拟通信过程即可得到结果并进行分析。
实验结果示例:
任务 3.2:吞吐量测试
任务要求:
1. 修改 TCP 和 QUIC 程序,实现大文件传输功能(如传输 100MB 的随机文件)
2. 在不同网络条件下测试吞吐量:
正常网络(无丢包)
使用 tc 模拟 5% 丢包率sudo tc qdisc add dev eth0 root netem loss 5%
使用 tc 模拟 100ms 延迟sudo tc qdisc add dev eth0 root netem delay 100ms
计算并对比两种协议的吞吐量MB/s
实验环境:
为了在Windows系统上实现第2点需要准备一个网络故障模拟工具clumsy,当然,
也可以在Windows系统下安装WSL2或者Linux虚拟机使用sudo tc命令运行相同的代码并
测试吞吐量。
本手册以clumsy为例进行教学使用WSL或虚拟机工具请自行学习。
首先打开clumsy的下载网址http://jagt.github.io/clumsy/download根据系统
版本下载对应的软件压缩包。解压后得到一个文件夹:
右键clumsy.exe以管理员身份运行其主界面如下
有疑问可以参考这篇博客:
https://blog.csdn.net/hgftgfffg/article/details/147412888
实验步骤:
1. 实现大文件传输功能
1 TCP程序
① 按照提示补全TCP程序即可
② 编译与运行
gcc -O2 tcp_server.c -o tcp_server.exe -lws2_32
gcc -O2 tcp_client.c -o tcp_client.exe -lws2_32
2 QUIC程序
① 按照提示补全QUIC程序即可
② 编译与运行
依旧参照之前的格式使用cl命令进行编译得到可运行文件后运行观察结
果。
2. 在不同网络条件下测试吞吐量
使用clumsy模拟 5% 丢包率首先以管理员身份打开clumsy.exe选择Lag=100m
s点击开始然后再次运行程序观察实验结果。
使用clumsy模拟 100ms 延迟首先以管理员身份打开clumsy.exe选择Lag=100m
s点击开始然后再次运行程序观察实验结果。
3. 实验结果示例:
此处仅提供了正常网络环境下tcp传输大文件的结果示例并且是以本地loopback
进行实验作为例子建议在自己做实验的时候可以改用本级IP尝试实现实验这样结
果会更加接近真实网络且clumsy对真实网卡路径更加稳定。
任务 3.3:多路复用性能测试
任务要求:
设计多流传输测试:同时建立 5 个 TCP 连接传输数据,在单个 QUIC 连接上建
立 5 个流传输数据,测量并对比两种方式的总传输时间和资源占用,分析 QUIC 多
路复用如何解决 TCP 的队头阻塞问题。
任务 3.4:网络异常恢复测试
任务要求:
模拟网络中断后恢复的场景:
建立连接并开始传输数据
使用tc qdisc add dev eth0 root netem loss 100%模拟网络中断
30 秒后使用tc qdisc del dev eth0 root恢复网络
对比两种协议的恢复能力和数据完整性
测试 QUIC 的连接迁移能力(服务器 IP 或端口变化后)