workflow系列教程(5-1)HTTP Server
往期教程
如果觉得写的可以,请给一个点赞+关注支持一下
观看之前请先看,往期的博客教程,否则这篇博客没办法看懂
-
workFlow c++异步网络库编译教程与简介
-
C++异步网络库workflow入门教程(1)HTTP任务
-
C++异步网络库workflow系列教程(2)redis任务
-
workflow系列教程(3)Series串联任务流
-
workflow系列教程(4)Parallel并联任务流
创建与启动http server
本示例里,我们采用http server的默认参数。创建和启动过程非常简单。
process为设置的异步回调函数server.start(port):中port参数表示监听的端口号
WFHttpServer server(process);
if (server.start(port) == 0)
{pause();server.stop();
}
start()接口有好几个重载函数,在WFServer.h里,可以看到如下一些接口:
class WFServerBase
{
public:/* To start TCP server. */int start(unsigned short port);int start(int family, unsigned short port);int start(const char *host, unsigned short port);int start(int family, const char *host, unsigned short port);int start(const struct sockaddr *bind_addr, socklen_t addrlen);/* To start an SSL server */int start(unsigned short port, const char *cert_file, const char *key_file);int start(int family, unsigned short port,const char *cert_file, const char *key_file);int start(const char *host, unsigned short port,const char *cert_file, const char *key_file);int start(int family, const char *host, unsigned short port,const char *cert_file, const char *key_file);int start(const struct sockaddr *bind_addr, socklen_t addrlen,const char *cert_file, const char *key_file);/* For graceful restart or multi-process server. */int serve(int listen_fd);int serve(int listen_fd, const char *cert_file, const char *key_file);/* Get the listening address. Used when started a server on a random port. */int get_listen_addr(struct sockaddr *addr, socklen_t *addrlen) const;
};
这些接口都比较好理解。任何一个start函数,当端口号为0时,将使用随机端口。此时用户可能需要在server启动完成之后通过get_listen_addr获得实际监听地址。
http echo server的业务逻辑
我们看到在构造http server的时候,传入了一个process参数,这也是一个std::function,定义如下:
using http_process_t = std::function<void (WFHttpTask *)>;
using WFHttpServer = WFServer<protocol::HttpRequest, protocol::HttpResponse>;template<>
WFHttpServer::WFServer(http_process_t proc) :WFServerBase(&HTTP_SERVER_PARAMS_DEFAULT),process(std::move(proc))
{
}
其实这个http_proccess_t和的http_callback_t类型是完全一样的。都是处理一个WFHttpTask。
对server来讲,我们的目标就是根据request,填写好response。
同样我们用一个普通函数实现process。逐条读出request的http header写入html页面。
void process(WFHttpTask *server_task)
{protocol::HttpRequest *req = server_task->get_req();protocol::HttpResponse *resp = server_task->get_resp();long seq = server_task->get_task_seq();protocol::HttpHeaderCursor cursor(req);std::string name;std::string value;char buf[8192];int len;/* Set response message body. */resp->append_output_body_nocopy("<html>", 6);len = snprintf(buf, 8192, "<p>%s %s %s</p>", req->get_method(),req->get_request_uri(), req->get_http_version());resp->append_output_body(buf, len);while (cursor.next(name, value)){len = snprintf(buf, 8192, "<p>%s: %s</p>", name.c_str(), value.c_str());resp->append_output_body(buf, len);}resp->append_output_body_nocopy("</html>", 7);/* Set status line if you like. */resp->set_http_version("HTTP/1.1");resp->set_status_code("200");resp->set_reason_phrase("OK");resp->add_header_pair("Content-Type", "text/html");resp->add_header_pair("Server", "Sogou WFHttpServer");if (seq == 9) /* no more than 10 requests on the same connection. */resp->add_header_pair("Connection", "close");struct sockaddr_in addr;socklen_t len = sizeof(addr);serverTask->get_peer_addr((sockaddr *)&addr,&len);if(addr.sin_family == AF_INET){fprintf(stderr,"sin_family:AF_INET\n");fprintf(stderr,"ip:%s\n", inet_ntoa(addr.sin_addr));fprintf(stderr,"port:%d\n",ntohs(addr.sin_port));}
}
set_http_version设置http版本set_status_code设置状态码set_reason_phrase设置响应dui’x
大多数HttpMessage相关操作之前已经介绍过了,在这里唯一的一个新操作是append_output_body()。
显然让用户生成完整的http body再传给我们并不太高效。用户只需要调用append接口,把离散的数据一块块扩展到message里就可以了。
append_output_body()操作会把数据复制走,另一个带_nocopy后缀的接口会直接引用指针,使用时需要注意不可以指向局部变量。
相关几个调用在HttpMessage.h可以看到其声明:
class HttpMessage
{
public:bool append_output_body(const void *buf, size_t size);bool append_output_body_nocopy(const void *buf, size_t size);...bool append_output_body(const std::string& buf);
};
再次强调,使用append_output_body_nocopy()接口时,buf指向的数据的生命周期至少需要延续到task的callback。
函数中另外一个变量seq,通过server_task->get_task_seq()得到,表示该请求是当前连接上的第几次请求,从0开始计。
程序中,完成10次请求之后就强行关闭连接,于是:
if (seq == 9) /* no more than 10 requests on the same connection. */resp->add_header_pair("Connection", "close");
关闭连接还可以通过task->set_keep_alive()接口来完成,但对于http协议,还是推荐使用设置header的方式。
这个示例中,因为返回的页面很小,我们没有关注回复成功与否。
相关文章:
workflow系列教程(5-1)HTTP Server
往期教程 如果觉得写的可以,请给一个点赞关注支持一下 观看之前请先看,往期的博客教程,否则这篇博客没办法看懂 workFlow c异步网络库编译教程与简介 C异步网络库workflow入门教程(1)HTTP任务 C异步网络库workflow系列教程(2)redis任务 workflow系列教程(3)Series串联任务流…...
php-使用wangeditor实现富文本(完成图片上传)-npm
官网参考连接:快速开始 | wangEditor 样式: 一、新建一个临时文件夹test1和一个文件夹wangeditor 临时文件夹test1:临时存放通过npm下载的文件文件夹wangeditor:用于存放在临时文件夹test1拷贝的css和js 二、安装 editor 在确保有…...
mysql查看数据库中所有的表的建表语句
mysql查看数据库中所有的表: SHOW TABLES; 这条命令将返回数据库中所有表的列表。 如果要查看单个表的建表语句,可以使用以下命令: SHOW CREATE TABLE table_name; 其中,"table_name"为你要查看的表的名称。 如果…...
【Axure RP9】实现登入效验及实现左侧菜单栏跳转各页面
目录 一 效验简介 1.1 校验好处 1.2 应用场景 二 登入校验 2.1 效果 2.2 实现流程 三 左边菜单栏左侧菜单栏跳转各页面 3.1 效果 3.2 实现图 一 效验简介 1.1 校验好处 提高安全性: 在传统的用户名和密码登录的基础上,引入了另一种或多种验证…...
76. 最小覆盖子串。优化官方题解!
leetcode原题如下: 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。 注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量…...
在国产GPU寒武纪MLU上快速上手Pytorch使用指南
本文旨在帮助Pytorch使用者快速上手使用寒武纪MLU。以代码块为主,文字尽可能简洁,许多部分对标NVIDIA CUDA。不正确的地方请留言更正。本文不定期更新。 文章目录 前言Cambricon PyTorch的Python包torch_mlu导入将模型加载到MLU上model.to(mlu)定义损失函…...
重生奇迹MU觉醒战士攻略
剑士连招技巧:生命之光:PK前起手式,增加血上限。 雷霆裂闪:眩晕住对手,剑士PK战士第一技能,雷霆裂闪是否使用好关系到胜负。 霹雳回旋斩:雷霆裂闪后可以选择用霹雳回旋斩跑出一定范围(因为对手…...
美颜技术详解:深入了解视频美颜SDK的工作机制
本文将深入探讨视频美颜SDK的工作机制,揭示其背后的科技奥秘和算法原理。 1.引言 视频美颜SDK作为一种集成到应用程序中的技术工具,通过先进的算法和图像处理技术,为用户提供令人印象深刻的实时美颜效果。 2.视频美颜SDK的基本工作原理 首…...
3D模型格式转换工具如何实现高性能数据转换?请看CAE系统开发实例!
客户背景 DP Technology是全球知名的CAM的供应商,在全球8个国家设有18个办事处。DP Technology提供的CAMESPRIT系统是一个用于数控编程,优化和仿真全方面的CAM系统。CAMESPRIT的客户来自多个行业,因此支持多种CAD工具和文件格式显得格外重…...
多级缓存:亿级流量的缓存方案
文章目录 一.多级缓存的引入二.JVM进程缓存三.Lua语法入门四.多级缓存1.OpenResty2.查询Tomcat3.Redis缓存预热4.查询Redis缓存5.Nginx本地缓存6.缓存同步 一.多级缓存的引入 传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未…...
C语言——高精度乘法
一、引子 高精度乘法相较于高精度加法和减法有更多的不同,加法和减法是一位对应一位进行操作的,而乘法是一个数的每一位对另一个数的每一位进行操作,需要的计算步骤更多。 二、核心算法 void Calculate(int num1[], int num2[], int numres…...
为什么C语言没有被C++所取代呢?
今日话题,为什么C语言没有被C所取代呢?虽然C是一个功能更强大的语言,但C语言在嵌入式领域仍然广泛使用,因为它更轻量级、更具可移植性,并且更适合在资源受限的环境中工作。这就是为什么C语言没有被C所取代的原因。如果…...
基于Spring的枚举类+策略模式设计(以实现多种第三方支付功能为例)
摘要 最近阅读《贯彻设计模式》这本书,里面使用一个更真实的项目来介绍设计模式的使用,相较于其它那些只会以披萨、厨师为例的设计模式书籍是有些进步。但这书有时候为了使用设计模式而强行朝着对应的 UML 图来设计类结构,并且对设计理念缺少…...
基于Linphone android sdk开发Android软话机
1.Linphone简介 1.1 简介 LinPhone是一个遵循GPL协议的开源网络电话或者IP语音电话(VOIP)系统,其主要如下。使用linphone,开发者可以在互联网上随意的通信,包括语音、视频、即时文本消息。linphone使用SIP协议&#…...
[论文分享]TimeDRL:多元时间序列的解纠缠表示学习
论文题目:TimeDRL: Disentangled Representation Learning for Multivariate Time-Series 论文地址:https://arxiv.org/abs/2312.04142 代码地址:暂无 关键要点:多元时间序列,自监督表征学习,分类和预测 摘…...
分享一个好看的vs主题
最近发现了一个很好看的vs主题(个人认为挺好看的),想要分享给大家。 主题的名字叫NightOwl,和vscode的主题颜色挺像的。操作方法也十分简单,首先我们先在最上面哪一行找到扩展。 然后点击管理扩展,再搜索栏…...
什么是云呼叫中心?
云呼叫中心作为一种高效的企业呼叫管理方案,越来越受到企业的青睐,常被用于管理客服和销售业务。那么,云呼叫中心到底是什么? 什么是云呼叫中心? 云呼叫中心是一种基于互联网的呼叫管理系统,与传统的呼叫…...
还在用nvm?来试试更快的node版本管理工具——fnm
前言 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步! 🍅 个人主页:南木元元 目录 什么是node版本管理 常见的node版本管理工具 fnm是什么 安装fnm …...
【Hadoop精讲】HDFS详解
目录 理论知识点 角色功能 元数据持久化 安全模式 SecondaryNameNode(SNN) 副本放置策略 HDFS写流程 HDFS读流程 HA高可用 CPA原则 Paxos算法 HA解决方案 HDFS-Fedration解决方案(联邦机制) 理论知识点 角色功能 元数据持久化 另一台机器就…...
企业需要哪些数字化管理系统?
企业需要哪些数字化管理系统? ✅企业引进管理系统肯定是为了帮助整合和管理大量的数据,从而优化业务流程,提高工作效率和生产力。 ❌但是,如果各个系统之间不互通、无法互相关联数据的话,反而会增加工作量和时间成本…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
