项目背景
由于我在宿舍有一台笔记本一台台式电脑,两个电脑经常需要互传一些文件,但是每次插拔U盘就显得很不优雅了,遂打算自己开发一个用于面对面传输的软件。
项目环境
win10操作系统、VS2019、HTTP第三方库httplib、boost/filesystem
使用技术
网络传输、HTTP/TCP协议、多线程、分块传输、STL
项目结构图
具体实现介绍
项目使用介绍
项目启动后,会自动启动服务端和客户端程序,用户通过客户端可以获取连接自己局域网的主机列表,选择指定主机获取其存储文件,再通过文件名下载具体文件。
项目文件结构
client.hpp包含发送1、获取连接请求2、获取文件列表请求3、获取指定文件请求的设置
server.hpp包含设置响应上面请求的方法
tool.hpp包含使用boost库接口,针对于文件创建,访问,更改等。
httplib.h是建立客户端和服务端的库
main.cpp因为是全双工通信,通过多线程的方式同时启动客户端和服务端。
模块介绍
客户端
1.局域网通信模块
基于网卡信息的获取和IP地址的管理,获取到当前所在局域网中所有IP地址
2.网络通信模块
基于http协议使用httplib搭建客户端,实现向服务端发送配对/列表获取/下载请求
3.文件分块模块
基于线程池,实现下载文件时,将所有文件下载进行分块传输
服务端
1.网络通信模块
基于http协议使用httpliba搭建服务端,实现对客户端主机匹配/列表获取/下载请求 的反应
2.文件操作模块
基于boost库的文件操作,实现指定目录下的文件迭代获取和文件的读写
具体接口介绍
客户端
- 发送文件配对请求
void HostPair(Host* host)
- 使用cpp-httplib搭建客户端
- 发送一个配对请求
- 根据服务端返回的响应状态码,判断是否配对成功
- 获取在线主机列表请求
bool GetOnlineHost()
- 先获取本机网卡信息,根据本机网卡信息去验证所有可能存在本机网卡组成的局域网中的在线主机
- 向所有可能ip地址发送配对请求,将配对成功的ip地址放到在线主机列表中
- 打印在线主机列表,用户选择要进行文件传输的主机
- 检查是否存在下载目录,没有将创建一个
- 获取指定主机文件列表
bool GetShareList(const std::string& host_ip)
获取在线主机列表的桩模块,主机配对成功后,客户端会直接向服务端请求文件列表
- 使用cpp-httplib搭建客户端
- 向服务端发送获取文件列表请求
- 将服务端返回的 内容打印,供用户选择
- 下载文件请求
bool DownloadFile(const std::string& host_ip, const std::string& file_name)
对于小于100M的文件,内存放的下,所以直接传输即可
- 分块下载
bool RangeDownLoad(const std::string& host_ip, const std::string& file_name)
- 对大于100M的文件进行分块传输,设置http头部字段range,向服务端多次发送请求
- 服务端根据range字段,返回对应区域的文件数据
- 客户端将数据写入文件对应位置。
服务端
这三个接口都是根据客户端请求对应设计的,作用是填充一个response对象,然后将response对象的内容填充到http响应中,返回给客户端
- 主机配对,确保对端主机在线
static void HostPair(const httplib::Request& req, httplib::Response& rsp)
- 分享文件列表,发送文件列表
static void ShareList(const httplib::Request& req, httplib::Response& rsp)
- 发送需要下载的文件
static void DownLoad(const httplib::Request& req, httplib::Response& rsp)
其他
cpp-httplib的大致实现内容:
- server类中有一个路由表,通过meht&path:调用对应的回调函数
- 每次接受一个客户端请求,使用线程池,开启一个线程进行处理,解析请求,得到request对象,查找路由表调用回调函数
- 回调函数的作用,将信息填充到response对象,再组织一个http响应获取response对象信息回复给客户端