1.14.C++项目:仿muduo库实现并发服务器之Util模块的设计

一、Util模块

在这里插入图片描述

二、实现思想

(一)管理

  1. 实现一些工具接口
  2. 读取文件内容
  3. 向文件写入内容
  4. URL编码
  5. URL解码
  6. 通过HTTP状态码获取描述信息
  7. 通过文件后缀名获取mime
  8. 判断一个文件是不是目录
  9. 判断一个文件是否是一个普通文件
  10. HTTP资源路径有效性判断

(二)意义

在协议支持模块中,当需要某些零碎功能的时候,便于使用!

(三)功能设计

class Util {public:// 字符串分割函数size_t Spilt();// 读取文件内容static bool ReadFile() {}// 向文件写入内容static bool  WriteFile();// URL编码static bool UrlEncode();// URL解码static bool UrlDecode();// 通过HTTP状态码获取描述信息static std::string StatusDesc();// 根据文件后缀名获取文件MINEstatic std::string ExtMine();// 判断一个文件是不是目录static bool IsDirectory();//判断一个文件是否是一个普通文件static bool IsRegular();//HTTP资源路径有效性判断static bool VaildPath();
};

三、代码

class Util {public://字符串分割函数,将src字符串按照sep字符进行分割,得到的各个字串放到arry中,最终返回字串的数量static size_t Split(const std::string &src, const std::string &sep, std::vector<std::string> *arry) {size_t offset = 0;// 有10个字符,offset是查找的起始位置,范围应该是0~9,offset==10就代表已经越界了while(offset < src.size()) {size_t pos = src.find(sep, offset);//在src字符串偏移量offset处,开始向后查找sep字符/字串,返回查找到的位置if (pos == std::string::npos) {//没有找到特定的字符//将剩余的部分当作一个字串,放入arry中if(pos == src.size()) break;arry->push_back(src.substr(offset));return arry->size();}if (pos == offset) {offset = pos + sep.size();continue;//当前字串是一个空的,没有内容}arry->push_back(src.substr(offset, pos - offset));offset = pos + sep.size();}return arry->size();}//读取文件的所有内容,将读取的内容放到一个Buffer中static bool ReadFile(const std::string &filename, std::string *buf) {std::ifstream ifs(filename, std::ios::binary);if (ifs.is_open() == false) {printf("OPEN %s FILE FAILED!!", filename.c_str());return false;}size_t fsize = 0;ifs.seekg(0, ifs.end);//跳转读写位置到末尾fsize = ifs.tellg();  //获取当前读写位置相对于起始位置的偏移量,从末尾偏移刚好就是文件大小ifs.seekg(0, ifs.beg);//跳转到起始位置buf->resize(fsize); //开辟文件大小的空间ifs.read(&(*buf)[0], fsize);if (ifs.good() == false) {printf("READ %s FILE FAILED!!", filename.c_str());ifs.close();return false;}ifs.close();return true;}//向文件写入数据static bool WriteFile(const std::string &filename, const std::string &buf) {std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);if (ofs.is_open() == false) {printf("OPEN %s FILE FAILED!!", filename.c_str());return false;}ofs.write(buf.c_str(), buf.size());if (ofs.good() == false) {ERR_LOG("WRITE %s FILE FAILED!", filename.c_str());ofs.close();    return false;}ofs.close();return true;}//URL编码,避免URL中资源路径与查询字符串中的特殊字符与HTTP请求中特殊字符产生歧义//编码格式:将特殊字符的ascii值,转换为两个16进制字符,前缀%   C++ -> C%2B%2B//不编码的特殊字符: RFC3986文档规定 . - _ ~ 字母,数字属于绝对不编码字符//RFC3986文档规定,编码格式 %HH //W3C标准中规定,查询字符串中的空格,需要编码为+, 解码则是+转空格static std::string UrlEncode(const std::string url, bool convert_space_to_plus) {std::string res;for (auto &c : url) {if (c == '.' || c == '-' || c == '_' || c == '~' || isalnum(c)) {res += c;continue;}if (c == ' ' && convert_space_to_plus == true) {res += '+';continue;}//剩下的字符都是需要编码成为 %HH 格式char tmp[4] = {0};//snprintf 与 printf比较类似,都是格式化字符串,只不过一个是打印,一个是放到一块空间中snprintf(tmp, 4, "%%%02X", c);res += tmp;}return res;}static char HEXTOI(char c) {if (c >= '0' && c <= '9') {return c - '0';}else if (c >= 'a' && c <= 'z') {return c - 'a' + 10;}else if (c >= 'A' && c <= 'Z') {return c - 'A' + 10;}return -1; }static std::string UrlDecode(const std::string url, bool convert_plus_to_space) {//遇到了%,则将紧随其后的2个字符,转换为数字,第一个数字左移4位,然后加上第二个数字  + -> 2b  %2b->2 << 4 + 11std::string res;for (int i = 0; i < url.size(); i++) {if (url[i] == '+' && convert_plus_to_space == true) {res += ' ';continue;}if (url[i] == '%' && (i + 2) < url.size()) {char v1 = HEXTOI(url[i + 1]);char v2 = HEXTOI(url[i + 2]);char v = v1 * 16 + v2;res += v;i += 2;continue;}res += url[i];}return res;}//响应状态码的描述信息获取static std::string StatuDesc(int statu) {auto it = _statu_msg.find(statu);if (it != _statu_msg.end()) {return it->second;}return "Unknow";}//根据文件后缀名获取文件mimestatic std::string ExtMime(const std::string &filename) {// a.b.txt  先获取文件扩展名size_t pos = filename.find_last_of('.');if (pos == std::string::npos) {return "application/octet-stream";}//根据扩展名,获取mimestd::string ext = filename.substr(pos);auto it = _mime_msg.find(ext);if (it == _mime_msg.end()) {return "application/octet-stream";}return it->second;}//判断一个文件是否是一个目录static bool IsDirectory(const std::string &filename) {struct stat st;int ret = stat(filename.c_str(), &st);if (ret < 0) {return false;}return S_ISDIR(st.st_mode);}//判断一个文件是否是一个普通文件static bool IsRegular(const std::string &filename) {struct stat st;int ret = stat(filename.c_str(), &st);if (ret < 0) {return false;}return S_ISREG(st.st_mode);}//http请求的资源路径有效性判断// /index.html  --- 前边的/叫做相对根目录  映射的是某个服务器上的子目录// 想表达的意思就是,客户端只能请求相对根目录中的资源,其他地方的资源都不予理会// /../login, 这个路径中的..会让路径的查找跑到相对根目录之外,这是不合理的,不安全的static bool ValidPath(const std::string &path) {//思想:按照/进行路径分割,根据有多少子目录,计算目录深度,有多少层,深度不能小于0std::vector<std::string> subdir;Split(path, "/", &subdir);int level = 0;for (auto &dir : subdir) {if (dir == "..") {level--; //任意一层走出相对根目录,就认为有问题if (level < 0) return false;continue;}level++;}return true;}
};

状态码:

std::unordered_map<int, std::string> _statu_msg = {{100,  "Continue"},{101,  "Switching Protocol"},{102,  "Processing"},{103,  "Early Hints"},{200,  "OK"},{201,  "Created"},{202,  "Accepted"},{203,  "Non-Authoritative Information"},{204,  "No Content"},{205,  "Reset Content"},{206,  "Partial Content"},{207,  "Multi-Status"},{208,  "Already Reported"},{226,  "IM Used"},{300,  "Multiple Choice"},{301,  "Moved Permanently"},{302,  "Found"},{303,  "See Other"},{304,  "Not Modified"},{305,  "Use Proxy"},{306,  "unused"},{307,  "Temporary Redirect"},{308,  "Permanent Redirect"},{400,  "Bad Request"},{401,  "Unauthorized"},{402,  "Payment Required"},{403,  "Forbidden"},{404,  "Not Found"},{405,  "Method Not Allowed"},{406,  "Not Acceptable"},{407,  "Proxy Authentication Required"},{408,  "Request Timeout"},{409,  "Conflict"},{410,  "Gone"},{411,  "Length Required"},{412,  "Precondition Failed"},{413,  "Payload Too Large"},{414,  "URI Too Long"},{415,  "Unsupported Media Type"},{416,  "Range Not Satisfiable"},{417,  "Expectation Failed"},{418,  "I'm a teapot"},{421,  "Misdirected Request"},{422,  "Unprocessable Entity"},{423,  "Locked"},{424,  "Failed Dependency"},{425,  "Too Early"},{426,  "Upgrade Required"},{428,  "Precondition Required"},{429,  "Too Many Requests"},{431,  "Request Header Fields Too Large"},{451,  "Unavailable For Legal Reasons"},{501,  "Not Implemented"},{502,  "Bad Gateway"},{503,  "Service Unavailable"},{504,  "Gateway Timeout"},{505,  "HTTP Version Not Supported"},{506,  "Variant Also Negotiates"},{507,  "Insufficient Storage"},{508,  "Loop Detected"},{510,  "Not Extended"},{511,  "Network Authentication Required"}
};std::unordered_map<std::string, std::string> _mime_msg = {{".aac",        "audio/aac"},{".abw",        "application/x-abiword"},{".arc",        "application/x-freearc"},{".avi",        "video/x-msvideo"},{".azw",        "application/vnd.amazon.ebook"},{".bin",        "application/octet-stream"},{".bmp",        "image/bmp"},{".bz",         "application/x-bzip"},{".bz2",        "application/x-bzip2"},{".csh",        "application/x-csh"},{".css",        "text/css"},{".csv",        "text/csv"},{".doc",        "application/msword"},{".docx",       "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},{".eot",        "application/vnd.ms-fontobject"},{".epub",       "application/epub+zip"},{".gif",        "image/gif"},{".htm",        "text/html"},{".html",       "text/html"},{".ico",        "image/vnd.microsoft.icon"},{".ics",        "text/calendar"},{".jar",        "application/java-archive"},{".jpeg",       "image/jpeg"},{".jpg",        "image/jpeg"},{".js",         "text/javascript"},{".json",       "application/json"},{".jsonld",     "application/ld+json"},{".mid",        "audio/midi"},{".midi",       "audio/x-midi"},{".mjs",        "text/javascript"},{".mp3",        "audio/mpeg"},{".mpeg",       "video/mpeg"},{".mpkg",       "application/vnd.apple.installer+xml"},{".odp",        "application/vnd.oasis.opendocument.presentation"},{".ods",        "application/vnd.oasis.opendocument.spreadsheet"},{".odt",        "application/vnd.oasis.opendocument.text"},{".oga",        "audio/ogg"},{".ogv",        "video/ogg"},{".ogx",        "application/ogg"},{".otf",        "font/otf"},{".png",        "image/png"},{".pdf",        "application/pdf"},{".ppt",        "application/vnd.ms-powerpoint"},{".pptx",       "application/vnd.openxmlformats-officedocument.presentationml.presentation"},{".rar",        "application/x-rar-compressed"},{".rtf",        "application/rtf"},{".sh",         "application/x-sh"},{".svg",        "image/svg+xml"},{".swf",        "application/x-shockwave-flash"},{".tar",        "application/x-tar"},{".tif",        "image/tiff"},{".tiff",       "image/tiff"},{".ttf",        "font/ttf"},{".txt",        "text/plain"},{".vsd",        "application/vnd.visio"},{".wav",        "audio/wav"},{".weba",       "audio/webm"},{".webm",       "video/webm"},{".webp",       "image/webp"},{".woff",       "font/woff"},{".woff2",      "font/woff2"},{".xhtml",      "application/xhtml+xml"},{".xls",        "application/vnd.ms-excel"},{".xlsx",       "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},{".xml",        "application/xml"},{".xul",        "application/vnd.mozilla.xul+xml"},{".zip",        "application/zip"},{".3gp",        "video/3gpp"},{".3g2",        "video/3gpp2"},{".7z",         "application/x-7z-compressed"}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/106484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

#力扣:LCR 182. 动态口令@FDDLC

LCR 182. 动态口令 一、Java class Solution {public String dynamicPassword(String password, int target) {return password.substring(target) password.substring(0, target);} } 二、C #include <string> using namespace std; class Solution { public:strin…

性能测试需求分析

1、客户方提出 客户方能提出明确的性能需求&#xff0c;说明对方很重视性能测试&#xff0c;这样的企业一般是金融、电信、银行、医疗器械等&#xff1b;他们一般对系统的性能要求非常高&#xff0c;对性能也非常了解。提出需求也比较明确。 曾经有一个银行项目&#xff0c;已经…

PCL 生成球形点云

目录 一、算法原理二、代码实现三、结果展示四、参考链接一、算法原理 生成球体点云的方法有很多种,Marsaglia于1972年提出了一个简单易行的实现方法,它从(-1,1)上的独立均匀分布中选取 x 1 x_1 x

多线程怎么共用一个事务

文章目录 场景分析测试对应的其他类我并没有贴出来,因为大家可以自己找个项目走一波测试testSession测试testTransaction 注意使用同一个sqlsession会导致线程安全问题,testSession方法就是在另外线程里面能读取到数据库里面没有的数据.但是有时候业务就是这么奇怪.扩展总结 场…

DetailView/货币详情页 的实现

1. 创建货币详情数据模型类 CoinDetailModel.swift import Foundation// JSON Data /*URL:https://api.coingecko.com/api/v3/coins/bitcoin?localizationfalse&tickersfalse&market_datafalse&community_datafalse&developer_datafalse&sparklinefalseR…

linux放开8080端口

linux放开8080端口 输入命令&#xff1a; 查看8080端口是否开放 firewall-cmd --query-port8080/tcpno显示端口未打开&#xff0c;yes表示开启&#xff0c;linux开启防火墙默认关闭8080端口 这里是引用&#xff1a;https://blog.csdn.net/weixin_54067866/article/details/1…

Excel 从网站获取表格

文章目录 导入网站数据导入股票实时行情 用 Excel 获取网站数据的缺点&#xff1a;只能获取表格类的数据&#xff0c;不能获取非结构化的数据。 导入网站数据 转到地址之后&#xff1a; 实测该功能经常导致 Excel 卡死。 导入股票实时行情

机器学习的原理是什么?

训过小狗没? 没训过的话总见过吧? 你要能理解怎么训狗&#xff0c;就能非常轻易的理解机器学习的原理. 比如你想教小狗学习动作“坐下”一开始小狗根本不知道你在说什么。但是如果你每次都说坐下”然后帮助它坐下&#xff0c;并给它一块小零食作为奖励&#xff0c;经过多次…

Docker在边缘计算中的崭露头角:探索容器技术如何驱动边缘计算的新浪潮

文章目录 第一部分&#xff1a;边缘计算和Docker容器边缘计算的定义Docker容器的崭露头角1. 可移植性2. 资源隔离3. 自动化部署和伸缩 第二部分&#xff1a;应用案例1. 边缘分析2. 工业自动化3. 远程办公 第三部分&#xff1a;挑战和解决方案1. 网络延迟2. 安全性3. 管理和部署…

边端小场景音视频流分发架构

备注&#xff1a;绿色线条&#xff0c;红色线条&#xff0c;蓝色线条&#xff0c;均是表示同一路流的不同的协议而已 1&#xff09;IPC本身的流媒体的能力有限&#xff0c;一般IPC支持的客户端数10~50个&#xff0c;媒体分发能力&#xff1a;10~20路&#xff0c;看设备品牌能力…

Android---DVM以及ART对JVM进行优化

Dalvik Dalvik 是 Google 公司自己设计用于 Android 平台的 Java 虚拟机&#xff0c;Android 工程师编写的 Java 或者 Kotlin 代码最终都是在这台虚拟机中被执行的。在 Android 5.0 之前叫作 DVM&#xff0c;5.0 之后改为 ART&#xff08;Android Runtime&#xff09;。在整个…

UGUI交互组件ScrollBar

一.ScrollBar的结构 对象说明Scrollbar挂有Image和Scrollbar组件的主体对象Sliding Area表示滑动范围Handle滑块 二.Scrollbar的属性 属性说明Handle Rect控制柄对象的引用Direction拖动控制柄时滚动条值增加的方向Value滚动条的当前值&#xff0c;范围为 0.0 到 1.0Suze控制柄…

Hadoop3教程(四):HDFS的读写流程及节点距离计算

文章目录 &#xff08;55&#xff09;HDFS 写数据流程&#xff08;56&#xff09; 节点距离计算&#xff08;57&#xff09;机架感知&#xff08;副本存储节点选择&#xff09;&#xff08;58&#xff09;HDFS 读数据流程参考文献 &#xff08;55&#xff09;HDFS 写数据流程 …

软件测试学习(四)自动测试和测试工具、缺陷轰炸、外包测试、计划测试工作、编写和跟踪测试用例

目录 自动测试和测试工具 工具和自动化的好处 测试工具 查看器和监视器 驱动程序 桩 压力和负载工具 干扰注入器和噪声发生器 分析工具 软件测试自动化 宏录制和回放 可编程的宏 完全可编程的自动测试工具 随机测试&#xff1a;猴子和大猩猩 使用测试工具和自动…

Shell命令笔记2

大家好&#xff0c;分享下最近工作中用得比较多的shell命令&#xff0c;希望对大家有帮助。 获取数组长度&#xff1a; ${#array_name[*]}获取脚本相对路径 script_path$(dirname "$0")获取脚本的名字 script_name$(basename "$0")获取脚本的绝对路径 …

如何从 Pod 内访问 Kubernetes 集群的 API

Kubernetes API 是您检查和管理集群操作的途径。您可以使用Kubectl CLI、工具(例如curl)或流行编程语言的官方集成库来使用 API 。 该 API 也可供集群内的应用程序使用。Kubernetes Pod 会自动获得对 API 的访问权限,并且可以使用提供的服务帐户进行身份验证。您可以通过使…

论文阅读:Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data

目录 摘要 Motivation 整体架构流程 技术细节 雷达和图像数据的同步 小结 论文地址: [2203.16258] Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data (arxiv.org) 论文代码&#xff1a;GitHub - valeoai/SLidR: Official PyTorch implementati…

深度学习—cv动物/植物数据集

文章目录 动物相关植物相关 动物相关 Edinburgh Pig Behavior Video Dataset:https://homepages.inf.ed.ac.uk/rbf/PIGDATA/ WLD 动物目标检测数据集: https://github.com/hellock/WLD 猪脸识别&#xff1a;https://blog.51cto.com/u_15404184/5289690 AFD动物面部数据集&…

【随笔】论多线程CPU离线渲染器的实现:A CPU BASED OFFLINE RENDERING ENGINE

前言 小熊挺喜欢玩游戏的&#xff0c;对于游戏画面有所追求&#xff0c;记得高中第一次玩战地的时候&#xff0c;惊叹于画面细腻的表现&#xff0c;并且还能开坦克车&#xff0c;这样的事情深深吸引了我。我是一个画面党&#xff0c;为了追求更好的画质表现我开始研究设置面板…

【Linux常用命令10】用户管理和文件权限命令

useradd&#xff1a;用于创建新的用户 useradd [选项] 用户名 参数 含义 -D 改变新建用户的预设值 -c 添加备注文字 -d 新用户每次登陆时所使用的家目录 -e 用户终止日期&#xff0c;日期的格式为YYYY-MM-DD -f 用户过期几日后永久停权。当值为0时用户立即被停权&a…