tcp/quic lab finished

This commit is contained in:
2025-12-25 14:33:29 +08:00
parent ac5b4bc15d
commit 200566e8fe
261 changed files with 2664 additions and 0 deletions

View File

@@ -0,0 +1,326 @@
任务一头歌平台编程实现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 或端口变化后)