# openhttps **Repository Path**: linyouhappy/openhttps ## Basic Information - **Project Name**: openhttps - **Description**: OpenHttps是一款Actor模式、组件设计的高性能、高并发的超轻量、超迷你的跨全平台Https框架。 使用OpenServer开源库开发,小巧迷你,支持IPv6,让C++开发Https如此简单,易如反掌。 由于时间关系,暂时没有实现状态机设计,不过使用OpenFSM库可以轻松实现状态机设计。 - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2023-04-06 - **Last Updated**: 2025-03-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OpenHttps OpenHttps是一款Actor模式、组件设计的高性能、高并发的超轻量、超迷你的跨全平台Https框架。 使用OpenServer开源库开发,小巧迷你,支持IPv6,让C++开发Https如此简单,易如反掌。 由于时间关系,暂时没有实现状态机设计,不过使用OpenFSM库可以轻松实现状态机设计。 OpenHttps也超容易实现Websocket,由于时间关系,暂时不实现。 作为一款C++的Http框架需要满足几点: 1. 高性能、高并发和跨全平台; 2. Actor模式、组件设计和状态机设计; 3. 任意组装,实现各种超难度的网络通信。 由于C++后端开发不适合协程,协程不在考虑范围。 **OpenLinyou致力于C++跨平台高并发高性能服务器框架开发,全平台设计,支持windows、linux、mac、安卓和iOS等平台,可以充分利用各平台的优势和工具,在VS或者XCode上开发写代码,做到一份代码跑全部平台。** OpenLinyou:https://www.openlinyou.com OpenHttps:https://github.com/openlinyou/openhttps https://gitee.com/linyouhappy/openhttps ## 跨平台支持 Linux和安卓使用epoll,Windows使用IOCP(wepoll),iOS和Mac使用kqueue,其他系统使用select。 ## 编译和执行 请安装cmake工具,用cmake可以构建出VS或者XCode工程,就可以在vs或者xcode上编译运行。 源代码:https://github.com/openlinyou/openhttps https://gitee.com/linyouhappy/openhttps https需要openssl支持。如果本地没有opessl库,需要先安装openssl库。如果不安装,关闭USE_OPEN_SSL宏定义。 ``` #克隆项目 git clone https://github.com/openlinyou/openhttps cd ./openhttps #创建build工程目录 mkdir build cd build cmake .. #如果是win32,在该目录出现openhttps.sln,点击它就可以启动vs写代码调试 make ./helloworld ``` ## 技术特点 OpenHttps的技术特点: 1. 跨全平台设计,此服务器框架可以运行在安卓和iOS上。 2. Linux和安卓使用epoll,Windows使用IOCP(wepoll),iOS和Mac使用kqueue,其他系统使用select。 3. 支持IPv6,小巧迷你,采用Actor模式和组件设计,通过组件去组装业务。 4. Actor模式和组件设计,可以非常容易实现高并发和分布式。也可以通过配置文件去定制业务和启动服务。 5. 一条线程一个actor,一个actor由多个组件组装。用玩积木的方式去做服务器开发。 ## 设计一个使用Https的科学上网工具 先声明:本例子只是展示OpenHttps的功能。由于科学上网涉及法律问题,由此造成的后果自己承担。 OpenHttps只是OpenServer技术的应用。具体用法见OpenServer。 OpenHttps只实现了三个组件OpenComHttpServer,OpenComHttpAgent和OpenComHttpClient。 OpenComHttpServer负责监听socket,与OpenComHttpAgent配合使用,OpenComHttpAgent处理具体的客户端通信,它们两组成一个web服务器。 OpenComHttpClient只是一个http客户端组件。 接下来就是组装出各自的server。 OpenHttpServer负责listen客户端连接,然后分发给OpenComHttpAgent,它的业务量不多只需要一个。 OpenHttpAgent1负责具体的客户端连接,需要处理大量的客户端连接。需要创建多个server,实现多核处理。 OpenHttpClient负责http客户端请求,可以用它来实现web服务器压力测试。 OpenHttps采用actor模式设计,启动它们只要向它们发送消息即可。 本展示的例子科学上网的原理。以访问https://www.bing.com 为例子。 假设服务器运行在本地电脑127.0.0.1上,类似海龟服务器。 在浏览器端,输入http://127.0.0.1/xx 。 使用浏览器插件,往http头加入client字段,client:https://www.bing.com. 浏览器就会请求127.0.0.1的服务器。 OpenHttpServer就会监听到浏览器的请求连接,把socket的fd发给OpenHttpAgent。 OpenHttpAgent解析http报文,发现http请求头含有client,进行移除,把url请求改成client指定的域名。然后把修改好的报文转发给OpenHttpClient。 OpenHttpClient再用修改的http报文向https://www.bing.com 请求。获得的数据立刻转发给OpenHttpAgent。OpenHttpAgent直接把接收到的数据立刻发给浏览器。 当然实际中,是没法实现科学上网的。因为科学上网很不稳定,容易掉包,网络连接超时等,都可能导致请求失败。 需要采用UDP方案,而Http协议天生适合UDP通信,由于涉及违法行为,不会提供任何代码。 ```C++ #include #include #include #include "openserver.h" #include "opencomhttpclient.h" #include "opencomhttpserver.h" using namespace open; class HttpApp :public OpenApp { int balance_; OpenServer* server_; std::vector accepts_; std::vector clients_; static HttpApp OpenApp_; public: static inline HttpApp& Instance() { return OpenApp_; } virtual void start() { OpenApp::start(); OpenTimer::Run(); OpenServer::RegisterCom("OpenComHttpServer"); OpenServer::RegisterCom("OpenComHttpAgent"); OpenServer::RegisterCom("OpenComHttpClient"); accepts_ = { OpenServer::StartServer("OpenHttpAgent1", { "OpenComHttpAgent" }), OpenServer::StartServer("OpenHttpAgent2", { "OpenComHttpAgent" }), OpenServer::StartServer("OpenHttpAgent3", { "OpenComHttpAgent" }), OpenServer::StartServer("OpenHttpAgent4", { "OpenComHttpAgent" }) }; server_ = OpenServer::StartServer("OpenHttpServer", { "OpenComHttpServer" }); assert(server_); balance_ = 0; clients_ = { OpenServer::StartServer("OpenHttpClient1", { "OpenComHttpClient" }), OpenServer::StartServer("OpenHttpClient2", { "OpenComHttpClient" }), OpenServer::StartServer("OpenHttpClient3", { "OpenComHttpClient" }), OpenServer::StartServer("OpenHttpClient4", { "OpenComHttpClient" }) }; } bool httpServer(std::shared_ptr& protoMsg) { for (size_t i = 0; i < accepts_.size(); i++) protoMsg->vectAccepts_.push_back(accepts_[i]->pid()); for (size_t i = 0; i < clients_.size(); i++) protoMsg->vectClients_.push_back(clients_[i]->pid()); auto proto = std::shared_ptr(new OpenMsgProto); proto->msg_ = protoMsg; bool ret = OpenThread::Send(server_->pid(), proto); assert(ret); return ret; } bool httpClient(std::shared_ptr& protoMsg, bool isAll) { if (clients_.empty()) { assert(false); return false; } //isAll auto proto = std::shared_ptr(new OpenMsgProto); proto->msg_ = protoMsg; bool ret = false; if (isAll) { for (size_t i = 0; i < clients_.size(); i++) { ret = OpenThread::Send(clients_[i]->pid(), proto); assert(ret); } } else { if (balance_ >= clients_.size()) balance_ = 0; OpenServer* client = clients_[balance_++]; ret = OpenThread::Send(client->pid(), proto); assert(ret); } return ret; } bool httpClient(std::shared_ptr& request) { if (clients_.empty()) { assert(false); return false; } auto protoMsg = std::shared_ptr(new OpenHttpClientSyncMsg); protoMsg->request_ = request; if (balance_ >= clients_.size()) { balance_ = 0; } OpenServer* client = clients_[balance_++]; auto proto = std::shared_ptr(new OpenMsgProto); proto->msg_ = protoMsg; bool ret = OpenThread::Send(client->pid(), proto); assert(ret); protoMsg->openSync_.await(); return ret; } }; HttpApp HttpApp::OpenApp_; void OnOpenHttpHandle(OpenHttpRequest& req, OpenHttpResponse& resp) { #ifdef USE_OPEN_SSL //80 redirect to 443 if (req.listenPort_ == 80) { resp.code_ = 302; resp["location"] = "https://" + req.host_ + ":" + std::to_string(req.port_) + "/" + req.url_; return; } #endif resp.response(".html", "

HelloWorld

" "

Welcome to OpenLinyou

"); } int main() { HttpApp::Instance().start(); printf("start HttpServer\n"); auto msg = std::shared_ptr(new OpenHttpServerMsg); msg->ip_ = "0.0.0.0"; #ifdef USE_OPEN_SSL msg->port_ = 443; msg->port1_ = 80; msg->isHttps_ = 1; msg->keyFile_ = "www.xx.com.key"; msg->certFile_ = "www.xx.com.crt"; #else msg->port_ = 80; msg->port1_ = 0; msg->isHttps_ = 0; #endif msg->handle_ = &OnOpenHttpHandle; HttpApp::Instance().httpServer(msg); //httpclient OpenThread::Sleep(500); auto request = std::shared_ptr(new OpenHttpRequest); request->method_ = "GET"; #ifdef USE_OPEN_SSL request->url_ = "https://www.xx.com/"; (*request)["client"] = "https://www.bing.com/"; #else request->url_ = "http://127.0.0.1/"; (*request)["client"] = "http://www.bing.com/"; #endif HttpApp::Instance().httpClient(request); auto& response = request->response_; std::string head; response.getHead(head); printf("[http client]code:%d, header:%s\n", response.code_, head.data()); std::string body; response.getBody(body); printf("[http client]body:%s\n", body.data()); HttpApp::Instance().wait(); return getchar(); } ```