P2P下载器(Linux下C++项⽬实战)
P2P下载器:即点对点下载器,服务端与客户端。服务端共享⽂件列表,客户端配对相应服务端,下载所需要的⽂件。
⼀、项⽬介绍
1.项⽬功能
搜索附近(局域⽹内)在线⽤户, 此处不⾜(只能在局域⽹内获取,需要⽹络穿透技术获取别的⽹络),获取到在线⽤户列表,可以查看指定⽤户的共享⽂件列表,然后对感兴趣的⽂件进⾏下载。
项⽬功能分为服务端和客户端的功能。
1)服务端
1.能够被附近客户端发现的功能(对主机配对请求进⾏⼀个响应)
2.提供客户端请求⽂件列表的功能。
3.提供客户端⽂件下载的功能。
2)客户端
1.搜索附近的主机(向局域⽹内⼴播⼀个主机配对请求)
2.获取指定主机的共享⽂件列表。
3.下载指定主机的指定⽂件。
2.实现技术
1)⽹络协议
服务端与客户端之间采⽤HTTP协议实现⽹络通信和⽂件传输。
2)httplib库来实现HTTP服务器
3)⼤⽂件多进程/多线程 数据分⽚传输(⽂件分块技术)
3.项⽬平台和⼯具
Centos7.2 vim/gcc/g++/gdb/make
必须在GCC 4.9版本以上开发此项⽬:
gcc具体更新步骤:
gcc升级:
yum install centos-release-scl-rh centos-release-scl
yum check-update
yum install devtoolset-4-gcc devtoolset-4-gcc-c++
source /opt/rh/devtoolset-4/enable
安oost库:sudo yum install boost + sudo yum install boost-devel
⼆、项⽬框架流程
1.整体框架
主控程序下服务端和客户端分别实现⾃⼰的功能。
在线代码运行器2.软件流程图
三、项⽬实现
1.使⽤httplib库搭建简单的HTTP服务器
HTTP协议回顾:
简单服务器实现代码如下:
#include "httplib.h"
using namespace httplib;
void HelloWorld(const Request &req, Response &rsp){
rsp.status = 302;
rsp.set_header("Location", "www.baidu");
rsp.body = "<html><h1>Hello World</h4></html>";
return;
}
int main(){
Server server;
server.Get("/", HelloWorld);
server.listen("0.0.0.0", 9000);
return 0;
}
运⾏服务器,在⽹页上输⼊本机的ip和指定port,即在⽹页上显⽰HELLOWORLD
2.测试获取局域⽹内所有主机地址
获取本机⽹络接⼝信息:getifaddr(&addr)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(){
struct ifaddrs* addrs;
getifaddrs(&addrs);
while(addrs != NULL){
struct sockaddr_in* ip = (struct sockaddr_in*)addrs->ifa_addr;
struct sockaddr_in* mask = (struct sockaddr_in*)addrs->ifa_netmask;
if(ip->sin_family != AF_INET){
addrs = addrs->ifa_next;
continue;
}
if(ip->sin_addr.s_addr == inet_addr("127.0.0.1")){
addrs = addrs->ifa_next;
continue;
}
printf("name:%s\n", addr->ifa_name);
printf("ip:%s\n", inet_ntoa(ip->sin_addr));
printf("mask:%s\n", inet_ntoa(mask->sin_addr));
uint32_t net = ntohl(ip->sin_addr.s_addr & mask->sin_addr.s_addr);
uint32_t host = ntohl(~mask->sin_addr.s_addr);
int i;
for(i =1; i < host; i++){
struct in_addr ip;
ip.s_addr = htonl(net + i);
printf("net:%s\n", ip.s_addr);
}
addrs = addrs->ifa_next;
}
return 0;
}
运⾏后打印:本机⽹卡名称,IP,⼦⽹掩码,和⽹络号内0--255的IP号
[test@localhost P2PProject]$ ./Getaddr
name:ens33
ip:192.168.78.128
mask:255.255.255.0
ip:192.168.78.0
ip:192.168.78.1
ip:192.168.78.2
ip:192.168.78.3
ip:192.168.78.4
ip:192.168.78.5
ip:192.168.78.6
ip:192.168.78.7
3.服务端功能
通过httplib搭建http服务器
步骤:1.实现主机配对的响应功能。 /hostpair -> 200
2.实现⽂件列表获取的响应功能。 /list -> 200
3.实现⽂件下载的响应功能。 /list/filename -> 200 filedata
把服务端封装成⼀个类:P2PServer
#include <iostream>
#include <boost/filesystem.hpp> //sudo yum install boost + sudo yum install boost-devel
#include <fstream>
#include "httplib.h"
using namespace httplib;
namespace bf = boost::filesystem;
#define SHARE_PATH "Download"
class P2PServer{
private:
Server _server;
private:
static void GetHostPair(const Request &req, Response &rsp); //设置请求状态重定向
static void GetFileLsit(const Request &req, Response &rsp); //获取⽂件列表
static void GetFileData(const Request &req, Response &rsp); //获取⽂件数据
public:
P2PServer(){
//判断共享⽬录若不存在,则创建
if(!bf::exists(SHARED_PATH)){
bf::create_directory((SHARED_PATH)));
}
bool Start(uint16_t port){
_server.Get("/hostpair", GetHostPair);
_server.Get("/list", GetFileLsit);
_server.Get("/list/(.*)", GetFileData);
_server.listen("0.0.0.0", port);
}
};
4.客户端功能
实现基于服务器HTTP的分块传输功能实现多进程⽂件分块下载功能的下载器,通过分块传输提⾼传输效率
实现步骤:1.获取局域⽹中的所有的主机IP地址。
2.获取在线主机列表(逐个向主机发送配对请求,判断相应状态)
3.打印在线主机列表,并且提供⽤户选择想要查看的主机共享⽂件列表
4.向选择的主机发送⽂件列表请求,获取到⽂件列表
5.打印⽂件列表,并且⽤户选择想要下载的⽂件
6.下载⽂件(向指定主机发送指定的⽂件下载请求)。
客户端封装为⼀个类:P2PClient
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <boost/system.hpp>
#include <boost/algorithm/string.hpp>
#include "httplib.h"
using namespace httplib;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论