基于C++实现的HTTP代理服务器设计

目录
实验一 HTTP代理服务器的设计与实现 1
一、 实验目的 1
二、 实验内容 1
(3) 扩展 HTTP 代理服务器,支持如下功能: 1
三、实验过程及结果 2
1、实验原理 2
(1) Socket 编程的客户端和服务器端主要步骤 2
(2)等待客户请求到达该端口; 2
(3)请求结束后关闭通信通道并终止。 3
(1)客户与服务器进程的作用是非对称的,因此代码不同。 3
(2) HTTP 代理服务器的基本原理与流程图 3
(3) HTTP 代理服务器实验验证过程以及实验结果 5
(4)实现 HTTP 代理服务器的关键技术及解决方案 11
5.代理服务器设置cahce实现方式 12
6. 网站过滤 13
7. 用户过滤 13
8.网站引导 13
四、实验心得 13
服务器端:
其过程是首先服务器方要先启动,并根据请求提供相应服务:
(1)打开一通信通道并告知本地主机,它愿意在某一公认地址上的某端口接收客户请求;对应的操作是申请一个socket,这时的socket称为“欢迎套接字”,然后绑定(bind)本地地址信息和欢迎套接字,然后开放监听(listen)。
(2)等待客户请求到达该端口;
(3)接收到客户端的服务请求时,处理该请求并发送应答信号。在TCP实现过程中进行了三次握手操作,但是实际编写过程中通过accept函数即可实现上述操作,并建立连接,注意这个时候才真正建立起了与客户机传输数据的套接字。接收到并发服务请求,要激活一新进程来处理这个客户请求。新进程处理此客户请求,并不需要对其它请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。
(4)返回第(2)步,等待另一客户请求。
(5)关闭服务器,对应的也就是关闭服务器的欢迎套接字。
客户端:
(1)打开一通信通道,即建立起要与服务器传输数据的套接字socket,通过connect连接到服务器所在主机的特定端口;
(2)向服务器发服务请求报文,等待并接收应答;继续提出请求…
(3)请求结束后关闭通信通道并终止。
从上面所描述过程可知:
(1)客户与服务器进程的作用是非对称的,因此代码不同。
(2)服务器进程一般是先启动的。只要系统运行,该服务进程一直存在,直到正常或强迫终止。
(2) HTTP 代理服务器的基本原理与流程图
代理服务器,俗称“翻墙软件”,允许一个网络终端(一般为客户端),通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。
如图 1-1 所示,为普通 Web 应用通信方式与采用代理服务器的通信方式的对比。
在这里插入图片描述

#pragma comment(lib,"Ws2_32.lib") 

#define MAXSIZE 65507 //发送数据报文的最大长度 
#define HTTP_PORT 80 //http 服务器端口 

#define CACHE_MAXSIZE 100
#define DATELENGTH 40
//Http 重要头部数据 
struct HttpHeader{
	char method[4]; // POST 或者 GET,注意有些为 CONNECT,本实验暂不考虑
	char url[1024];  //  请求的 url 
	char host[1024]; //  目标主机 
	char cookie[1024 * 10]; //cookie 
	HttpHeader(){
		ZeroMemory(this, sizeof(HttpHeader));
	}
};
//这个是高仿的htpp的头部数据,用于在cache中找到对象,但是节约了cookie的空间
struct cache_HttpHeader{
	char method[4]; // POST 或者 GET,注意有些为 CONNECT,本实验暂不考虑
	char url[1024];  //  请求的 url 
	char host[1024]; //  目标主机 
	cache_HttpHeader(){
		ZeroMemory(this, sizeof(cache_HttpHeader));
	}
};
//实现代理服务器的缓存技术
struct __CACHE{
	cache_HttpHeader htphed;
	char buffer[MAXSIZE];
	char date[DATELENGTH];//存储的更新时间
	__CACHE(){
		ZeroMemory(this->buffer, MAXSIZE);
		ZeroMemory(this->buffer, sizeof(date));
	}

};
int __CACHE_number = 0;//标记下一个应该放缓存的位置
__CACHE cache[CACHE_MAXSIZE];//真`缓存

BOOL InitSocket();
BOOL ParseHttpHead(char *buffer, HttpHeader * httpHeader);
BOOL ConnectToServer(SOCKET *serverSocket, char *host);
unsigned int __stdcall ProxyThread(LPVOID lpParameter);
int Cache_find(__CACHE *cache, HttpHeader htp);

//代理相关参数 
SOCKET ProxyServer;
sockaddr_in ProxyServerAddr;
const int ProxyPort = 10240;
//禁止访问的主机,禁用网站
char* host[10] = { "today.hit.edu.cn", "jwts.hit.edu.cn", "resource.hit.edu.cn", "www.hit.edu.cn" };
const int host_number =  4;

//网站诱导
char* host_to_another = "djangobook.py3k.cn" ;//诱导到pt.hit.edu.cn,url=http://pt.hit.edu.cn/  ,url源=http://djangobook.py3k.cn/2.0/
char* another[2] = { "pt.hit.edu.cn","http://pt.hit.edu.cn/" };//跳转到的地址
//char* host_to_another = "www.pku.edu.cn";
//char* another[2] = { "today.hit.edu.cn", "http://today.hit.edu.cn/" };
//char Cache[][];
//由于新的连接都使用新线程进行处理,对线程的频繁的创建和销毁特别浪费资源
//可以使用线程池技术提高服务器效率 
//const int ProxyThreadMaxNum = 20; 
//HANDLE ProxyThreadHandle[ProxyThreadMaxNum] = {0}; 
//DWORD ProxyThreadDW[ProxyThreadMaxNum] = {0}; 
struct ProxyParam{
	SOCKET clientSocket;
	SOCKET serverSocket;
};

int _tmain(int argc, _TCHAR* argv[])
{
	
	printf("代理服务器正在启动\n");
	printf("初始化...\n");
	if (!InitSocket()){

		printf("socket 初始化失败\n");
		return -1;
	}
	printf("代理服务器正在运行,监听端口  %d\n", ProxyPort);
	SOCKET acceptSocket = INVALID_SOCKET;
	ProxyParam *lpProxyParam;
	HANDLE hThread;
	DWORD dwThreadID;
	//代理服务器不断监听 
	sockaddr_in verAddr;
	int hahaha = sizeof(SOCKADDR);
	while (true){
		acceptSocket = accept(ProxyServer, (SOCKADDR*)&verAddr, &(hahaha));
		lpProxyParam = new ProxyParam;
		if (lpProxyParam == NULL){
			continue;
		}
		if (!strcmp("127.0.0.1", inet_ntoa(verAddr.sin_addr))){
			printf("被限制的用户访问!\n");
			continue;
		}
		lpProxyParam->clientSocket = acceptSocket;
		hThread = (HANDLE)_beginthreadex(NULL, 0,
			&ProxyThread, (LPVOID)lpProxyParam, 0, 0);
		CloseHandle(hThread);
		Sleep(200);
	}
	closesocket(ProxyServer);
	WSACleanup();
	return 0;
}


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1.项目代码均经过功能验证ok,确保稳定可靠运行。欢迎下载体验!下载完使用问题请私信沟通。 2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【资源说明】 基于C++实现的轻量级Web服务器源码+项目说明.zip 开发部署环境 操作系统: Ubuntu 16.04 编译器: g++ 5.4 版本控制: git 自动化构建: cmake 集成开发工具: CLion 编辑器: Vim 压测工具:WebBench 核心功能及技术 状态机解析HTTP请求,目前支持 HTTP GET、HEAD方法 添加定时器支持HTTP长连接,定时回调handler处理超时连接 使用 priority queue 实现的最小堆结构管理定时器,使用标记删除,以支持惰性删除,提高性能 使用epoll + 非阻塞IO + 边缘触发(ET) 实现高并发处理请求,使用Reactor编程模型 epoll使用EPOLLONESHOT保证一个socket连接在任意时刻都只被一个线程处理 使用线程池提高并发度,并降低频繁创建线程的开销 同步互斥的介绍 使用RAII手法封装互斥器(pthrea_mutex_t)、 条件变量(pthread_cond_t)等线程同步互斥机制,使用RAII管理文件描述符等资源 使用shared_ptr、weak_ptr管理指针,防止内存泄漏 下一步开发计划 添加异步日志系统,记录服务器运行状态 增加json配置文件,支持类似nginx的多网站配置 提供CGI支持 类似nginx的反向代理和负载均衡 必要时增加可复用内存池。
Mosquitto本身是一个MQTT代理,而不是一个MQTT服务器。如果你需要一个MQTT服务器,可以考虑使用Eclipse Mosquitto的扩展版本Mosquitto.rsmb,它提供了一个MQTT服务器实现,可以用来实现自己的MQTT服务器。 以下是一个基于Mosquitto.rsmb的MQTT C++服务器端示例代码: ```cpp #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <unistd.h> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <mosquitto.h> #include <pthread.h> #define MQTT_PORT 1883 #define MQTT_KEEP_ALIVE 60 #define MAX_CLIENTS 1024 static void on_connect(struct mosquitto *mosq, void *userdata, int rc) { if (rc == 0) { std::cout << "Connected to MQTT broker" << std::endl; } else { std::cerr << "Failed to connect to MQTT broker: " << mosquitto_connack_string(rc) << std::endl; } } static void on_message(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *msg) { std::cout << "Received message on topic " << msg->topic << ": " << (char *)msg->payload << std::endl; } class Client { public: Client(int fd) : fd_(fd), mosq_(NULL) {} ~Client() { if (mosq_) { mosquitto_destroy(mosq_); mosq_ = NULL; } if (fd_ > 0) { close(fd_); fd_ = -1; } } int fd() const { return fd_; } void start() { mosq_ = mosquitto_new(NULL, true, this); if (!mosq_) { std::cerr << "Failed to create Mosquitto object" << std::endl; return; } mosquitto_connect_callback_set(mosq_, on_connect); mosquitto_message_callback_set(mosq_, on_message); int rc = mosquitto_socket(mosq_); if (rc == MOSQ_ERR_SUCCESS) { rc = mosquitto_loop_start(mosq_); } if (rc != MOSQ_ERR_SUCCESS) { std::cerr << "Failed to start Mosquitto loop: " << mosquitto_strerror(rc) << std::endl; return; } char buf[1024]; while (true) { int n = recv(fd_, buf, sizeof(buf), 0); if (n <= 0) { break; } mosquitto_raw_publish(mosq_, NULL, "test_topic", n, buf, 0, false); } } private: int fd_; struct mosquitto *mosq_; }; void *client_handler(void *arg) { Client *client = (Client *)arg; client->start(); delete client; return NULL; } int main(int argc, char **argv) { int listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { perror("Failed to create socket"); return 1; } struct sockaddr_in addr; std::memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(MQTT_PORT); int optval = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("Failed to bind socket"); return 1; } if (listen(listen_fd, SOMAXCONN) < 0) { perror("Failed to listen on socket"); return 1; } std::cout << "Listening on port " << MQTT_PORT << std::endl; while (true) { int conn_fd = accept(listen_fd, NULL, NULL); if (conn_fd < 0) { perror("Failed to accept connection"); continue; } std::cout << "Accepted connection from " << inet_ntoa(addr.sin_addr) << std::endl; pthread_t tid; pthread_create(&tid, NULL, client_handler, new Client(conn_fd)); pthread_detach(tid); } close(listen_fd); return 0; } ``` 此代码使用Mosquitto.rsmb作为MQTT服务器,并在本地的1883端口监听连接。在接受到客户端连接之后,它会启动一个新线程来处理该客户端连接。在处理过程中,它会接收客户端的消息,并使用Mosquitto API将其发布到名为“test_topic”的主题上。 请注意,此代码仅供参考,并不是一个完整的MQTT服务器实现。在实际使用中,还需要考虑安全性、可靠性、性能等因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shejizuopin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值