当前位置: 首页 > news >正文

太原网站维护安溪县住房和城乡建设网站

太原网站维护,安溪县住房和城乡建设网站,英文网站开发哪家好,专业网站设计公司哪里有前些天发现了一个巨牛的人工智能学习网站#xff0c;通俗易懂#xff0c;风趣幽默#xff0c;忍不住分享一下给大家。点击跳转到网站 #x1f308;个人主页#xff1a; 南桥几晴秋 #x1f308;C专栏#xff1a; 南桥谈C #x1f308;C语言专栏#xff1a; C语言学习系… 前些天发现了一个巨牛的人工智能学习网站通俗易懂风趣幽默忍不住分享一下给大家。点击跳转到网站 个人主页 南桥几晴秋 C专栏 南桥谈C C语言专栏 C语言学习系列 Linux学习专栏 南桥谈Linux 数据结构学习专栏 数据结构杂谈 数据库学习专栏 南桥谈MySQL Qt学习专栏 南桥谈Qt 菜鸡代码练习 练习随想记录 git学习 南桥谈Git 本科在读菜鸡一枚指出问题及时改正 文章目录 前言HTTP协议URLurlencode 和 urldecode了解 HTTP协议请求与响应格式简单实现一个HTTP服务器HTTP请求及反序列化HTTP请求的基本框架封装反序列化获取每一行Getline进一步解析请求行进一步解析请求报头测试 HTTP响应及序列化HTTP响应基本框架封装序列化使用telnet进行抓包完整代码测试为什么只访问首页时但是依然有下面的图片 理解网站页面跳转HTTP 常见 Header关于connection报头 HTTP的状态码永久重定向与临时重定向HTTP请求方法HTTP常见方法GET方法POST方法 完整HTTP代码 前言 实现一个简单的HTTP服务器点击链接获取源码 HTTP协议 应用层有很多协议其中HTTP协议就是其中一个HTTP协议超文本传输协议也是较为重要的一个协议。 在互联网世界中 HTTPHyperText Transfer Protocol 超文本传输协议 是一个至关重要的协议。 它定义了客户端如浏览器 与服务器之间如何通信 以交换或传输超文本如 HTML 文档。 HTTP 协议是客户端与服务器之间通信的基础。 客户端通过 HTTP 协议向服务器发送请求 服务器收到请求后处理并返回响应。 HTTP 协议是一个无连接、 无状态的协议 即每次请求都需要建立新的连接 且服务器不会保存客户端的状态信息。 URL 说到URL大家可能不熟悉但是说到“网址”大家就一目了然实际上“网址”就是URL。 域名会自动转化成IP地址称为DNS协议名称和端口号是强关联的在浏览器这个网址中将端口号默认忽略了当浏览器发起请求时会自动拼接端口号80指明端口 HTTP做的工作用户在网络上获取资源图片、文本、视频等时是在服务器端获取所有的资源都是在服务器端。通过某种协议如http协议或者https协议来标识用户所需要的资源然后返回给用户。 我们知道Linux适合做后端开发那么这些服务器端的资源是在Linux操作系统中。而Linux操作系统一切皆文件必须得找到对应的资源需要通过路径来标识因此在URL后半部分就是路径。 因此URL就是统一资源定位符域名文件路径标识互联网中唯一的文件资源。 urlencode 和 urldecode了解 像 / ? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现。比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义。 转义的规则如下: 将需要转码的字符转为 16 进制 然后从右到左 取 4 位(不足 4 位直接处理) 每 2 位做一位 前面加上% 编码成%XY 格式。 HTTP协议请求与响应格式 HTTP请求 在HTTP请求中格式如下 首行称之为请求行格式为 方法POST、GET、HEAD…URI即URL后半部分—用户访问资源的路径版本号 HTTP的方法 HTTP响应 在HTTP请求中格式如下 这里的DATA是用户需要的资源内容网页图片的二进制、视频的二进制、音频的二进制等 HTTP中如何将报头和有效载荷进行分离封装 通过空行即\r\n 如何HTTP的请求和响应读到一个完整的报头通过换行符可以知道读到一个完整的报文。 如果请求和响应中包含了正文DATA如何保证读到一个完整的报头怎么知道正文部分的长度在之前的网络版本计算器中只有一个字段拥有有效载荷长度的字段。在HTTP的请求和应答中报头属性中有一个公共属性叫做Content-Length: xxx无论是请求还是响应如果有正文部分那么这个字段一定包含这样就能读到一个完整的报文。 简单实现一个HTTP服务器 HTTP请求及反序列化 HTTP请求的基本框架 在HTTP请求中需要基本的属性请求行、请求报头、空行、请求正文以及进一步显示出具体属性使用的方法、使用的URL、使用的HTTP版本、请求报头以KV形式显示 class HttpRequest { public:HttpRequest():_blank_line(base_sep) {}void Deserialize(std::string reqstr){}~HttpRequest() {} private:// 请求的基本格式std::string _req_line;std::vectorstd::string _req_handers;std::string _blank_line;std::string _body_text;//具体属性std::string _method;std::string _url;std::string _version;std::unordered_mapstd::string,std::string _headers_kv; };封装反序列化 在反序列化中 首先需要通过Getline从reqstr中获取请求行获取请求报头通过一个 do-while 循环来读取所有的请求头部信息。每次循环调用 Getline(reqstr) 获取一行数据并将它存储在 header 中获取请求正文进一步解析请求行和请求头 void Deserialize(std::string reqstr) {// 基本的反序列化_req_lineGetline(reqstr);std::string header;do{headerGetline(reqstr);if(header.empty()) break;else if(headerbase_sep) break;_req_handers.push_back(header);}while(true);if(!reqstr.empty())_body_textreqstr;//进一步反序列化ParseReqLine();ParseReqHeader(); }获取每一行Getline 寻找base_sep的位置如果找不到说明没有分隔符是一个空串如果找到了base_sep就分割从0到base_sep之间的字符串。然后更新reqstr即删除已经提取的部分。如果 line 是空字符串即没有有效的行内容则返回 base_sep表示一个空行或分隔符。否则返回提取的有效行内容 line。 const static std::string base_sep\r\n;std::string Getline(std::string reqstr) {auto posreqstr.find(base_sep);if(posstd::string::npos) return std::string();std::string linereqstr.substr(0,pos);reqstr.erase(0,line.size()base_sep.size());return line.empty()?base_sep:line; }进一步解析请求行 解析一个请求行并将解析的结果存储到类的成员变量 _method、_url 和 _version 中。 代码通过 std::stringstream 提供的流提取操作符 () 来从 ss 中依次提取数据并赋值给 _method、_url 和 _version。 第一个 _method将从流中提取的第一个单词如 GET赋值给 _method。通常情况下_method 代表 HTTP 请求的方法例如 GET、POST 等。第二个 _url提取流中的第二个单词如 /index.html并将其赋值给 _url。这个字符串通常代表请求的 URL 路径。第三个 _version提取流中的第三个单词如 HTTP/1.1并将其赋值给 _version。这个字符串代表请求的 HTTP 版本。 void ParseReqLine() {std::stringstream ss(_req_line);ss_method_url_version; }进一步解析请求报头 未解析的解析报头是以: 分割的因此这里使用: 作为分隔符。 将每个请求头的键值对存储到 _headers_kv 容器中。它通过遍历 _req_handers提取出每个请求头的键和值并将它们插入到一个键值对容器中。 const static std::string line_sep: ;void ParseReqHeader(){for(auto header:_req_handers){auto posheader.find(line_sep);if(posstd::string::npos) continue;std::string kheader.substr(0,pos); // [)std::string vheader.substr(posline_sep.size());if(k.empty()||v.empty()) continue;_headers_kv.insert(std::make_pair(k,v));}}测试 HTTP响应及序列化 HTTP响应基本框架 class HttpResponse { public:HttpResponse():_version(httpversion),_blank_line(base_sep){}void AddCode(int code){_status_codecode;_descOK;}void AddHeader(const std::string k,const std::string v){_headers_kv[k]v;}void AddBodyText(const std::string body_text){_resp_body_textbody_text;}std::string Serialize(){}~HttpResponse(){}private:// 基本属性std::string _version;int _status_code;std::string _desc;std::unordered_mapstd::string,std::string _headers_kv;// 响应的基本格式std::string _status_line;std::vectorstd::string _resp_handers;std::string _blank_line;std::string _resp_body_text; };封装序列化 在HTTP响应序列化中 构建状态行并将其存储在 _status_line 字符串中构建响应头遍历 _headers_kv 容器它是一个存储 HTTP 响应头的键值对容器。每一行头部字符串会被 push_back 到 _resp_handers 容器中最终该容器保存了所有响应头的字符串正式序列化将之前构建的各部分拼接成最终的响应报文字符串 responsestr std::string Serialize() {// 构建状态行_status_line_versionspacesepstd::to_string(_status_code)spacesep_descbase_sep;// 构建应答报头for(auto hander:_headers_kv){std::string header_linehander.firstline_sephander.secondbase_sep;_resp_handers.push_back(header_line);}// 空行和正文// 空行已经初始化正文已经保存在_resp_body_text中// 正式序列化std::string responsestr_status_line;for(auto line:_resp_handers){responsestrline;}responsestr_blank_line;responsestr_resp_body_text;return responsestr; }使用telnet进行抓包 telnet 127.0.0.1 8888 通过这个测试得到响应 完整代码 class HttpResponse { public:HttpResponse():_version(httpversion),_blank_line(base_sep){}void AddCode(int code){_status_codecode;_descOK;}void AddHeader(const std::string k,const std::string v){_headers_kv[k]v;}void AddBodyText(const std::string body_text){_resp_body_textbody_text;}std::string Serialize(){// 构建状态行_status_line_versionspacesepstd::to_string(_status_code)spacesep_descbase_sep;// 构建应答报头for(auto hander:_headers_kv){std::string header_linehander.firstline_sephander.secondbase_sep;_resp_handers.push_back(header_line);}// 空行和正文// 空行已经初始化正文已经保存在_resp_body_text中// 正式序列化std::string responsestr_status_line;for(auto line:_resp_handers){responsestrline;}responsestr_blank_line;responsestr_resp_body_text;return responsestr;}~HttpResponse(){}private:// 基本属性std::string _version;int _status_code;std::string _desc;std::unordered_mapstd::string,std::string _headers_kv;// 响应的基本格式std::string _status_line;std::vectorstd::string _resp_handers;std::string _blank_line;std::string _resp_body_text; };html !DOCTYPE html html headtitle南桥几晴秋(gwj.cn)/title meta charsetUTF-8 /head bodydiv idcontainer stylewidth:800pxdiv idheader stylebackground-color:#FFA500;h1 stylemargin-bottom:0;南桥几晴秋/h1/divdiv idmenu stylebackground-color:#FFD700;height:200px;width:100px;float:left;bMenu/bbrHTMLbrCSSbrJavaScript/divdiv idcontent stylebackground-color:#EEEEEE;height:200px;width:700px;float:left;这是一个测试/divdiv idfooter stylebackground-color:#FFA500;clear:both;text-align:center;Copyright © gwj.com/div/divdivimg src/image/1.jpg alt一张图片/div /body /html测试 在浏览器中输入http://119.3.220.34:8888/得到如下界面 为什么只访问首页时但是依然有下面的图片 获得一个完整的网页浏览器要先得到html根据html的标签检测出我们还要获取的其他资源浏览器会继续发起HTTP请求。 理解网站页面跳转 我们在使用网站时点击某个按钮进行跳转实际上是在访问wwwroot中的文件 在我自己的HTTP服务器中显示如下 在现代Web开发中HTML文件的内容通常属于前端部分而通过后端调用和渲染这些内容是常见的架构设计。 HTTP 常见 Header Content-Type: 数据类型(text/html 等)Content-Length: Body 的长度Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;User-Agent: 声明用户的操作系统和浏览器版本信息;referer: 当前页面是从哪个页面跳转过来的Location: 搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能; 关于connection报头 HTTP 中的 Connection 字段是 HTTP 报文头的一部分 它主要用于控制和管理客户端与服务器之间的连接状态。 管理持久连接 Connection 字段还用于管理持久连接也称为长连接 。 持久连接允许客户端和服务器在请求/响应完成后不立即关闭 TCP 连接 以便在同一个连接上发送多个请求和接收多个响应。HTTP/1.1 在 HTTP/1.1 协议中 默认使用持久连接。 当客户端和服务器都不明确指定关闭连接时 连接将保持打开状态 以便后续的请求和响应可以复用同一个连接。HTTP/1.0 在 HTTP/1.0 协议中 默认连接是非持久的。 如果希望在 HTTP/1.0上实现持久连接 需要在请求头中显式设置 Connection: keep-alive 语法格式 • Connection: keep-alive 表示希望保持连接以复用 TCP 连接。 • Connection: close 表示请求/响应完成后 应该关闭 TCP 连接。 HTTP的状态码 最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定 向), 504(Bad Gateway) 永久重定向与临时重定向 什么叫做重定向 用户浏览器想目标服务器发起请求但是目标服务器想用户浏览器推送了一个服务器此时用户浏览器向推送的服务器进行请求重定向的地址在location字段中。 所谓的永久与临时无非就是字面意思永久即下次再请求时直接去新的服务器会修改客户的地址临时不对客户做任何影响。 永久重定向当你决定将一个页面永久迁移到新地址时使用永久重定向是正确的做法。例如网站改版、页面URL结构优化或域名更换时。 临时重定向当你需要在短期内将页面临时指向另一个URL时使用比如进行系统维护、A/B测试或者临时更新页面内容时。 if(req.Path()wwwroot/redir) {std::string reire_pathhttps://www.qq.com;resp.AddCode(302,_code_to_desc[302]);resp.AddHeader(Location,reire_path); }HTTP请求方法 HTTP常见方法 GET方法 用途用于请求URL指定的资源特性指定资源经服务器端解析后返回响应内容 GET一般用来获取静态资源也可以通过URL向服务器传递参数 std::string Method() {LOG(DEBUG,Client request method is %s\n,_method.c_str());return _method; }POST方法 用途用于传输实体的主体 通常用于提交表单数据特性可以发送大量的数据给服务器 并且数据包含在请求体中 POST方法可以通过httprequest的正文来进行参数传递 POST方法传递参数比GET方法更私密登录信息不回显示在浏览器中。但是都不安全。要想保证安全必须对http的参数部分进行加密。 完整HTTP代码 #pragma once#includeiostream #includestring #includevector #includefunctional #includesstream #includefstream #includeunordered_mapconst static std::string base_sep\r\n; const static std::string line_sep: ; const static std::string prefixpathwwwroot; // web根目录 const static std::string homepageindex.html; // web根目录 const static std::string httpversionHTTP/gwj_1.0; const static std::string spacesep ; const static std::string suffixsep.; const static std::string html_404404.html; const static std::string arg_sep?;class HttpRequest { private:std::string Getline(std::string reqstr){auto posreqstr.find(base_sep);if(posstd::string::npos) return std::string();std::string linereqstr.substr(0,pos);reqstr.erase(0,line.size()base_sep.size());return line.empty()?base_sep:line;}void ParseReqLine(){std::stringstream ss(_req_line);ss_method_url_version;if(strcasecmp(_method.c_str(),GET)0){auto pos_url.find(arg_sep);if(pos!std::string::npos){_body_text_url.substr(posarg_sep.size());_url.resize(pos); // 只保留了前面的字符}}_path_url;if(_path[_path.size()-1]/){_pathhomepage;}auto pos_path.rfind(suffixsep);if(pos!std::string::npos){_suffix_path.substr(pos);}else{_suffix.default;}}void ParseReqHeader(){for(auto header:_req_handers){auto posheader.find(line_sep);if(posstd::string::npos) continue;std::string kheader.substr(0,pos); // [)std::string vheader.substr(posline_sep.size());if(k.empty()||v.empty()) continue;_headers_kv.insert(std::make_pair(k,v));}}public:HttpRequest():_blank_line(base_sep),_path(prefixpath){}void Deserialize(std::string reqstr){// 基本的反序列化_req_lineGetline(reqstr);std::string header;do{headerGetline(reqstr);if(header.empty()) break;else if(headerbase_sep) break;_req_handers.push_back(header);}while(true);if(!reqstr.empty())_body_textreqstr;//进一步反序列化ParseReqLine();ParseReqHeader();}std::string Url(){LOG(DEBUG,Client Want path %s\n,_path.c_str());return _url;}std::string Path(){LOG(DEBUG,Client Want %s\n,_url.c_str());return _path;}std::string Suffix(){return _suffix;}std::string Method(){LOG(DEBUG,Client request method is %s\n,_method.c_str());return _method;}std::string GetRequestBody(){LOG(DEBUG,Client request method is %s, args: %s, request path: %s\n,_method.c_str(),_body_text.c_str(),_path.c_str());return _body_text;}void Print(){std::cout-----------------------------------------------std::endl;std::cout###_req_linestd::endl;for(auto header:_req_handers){std::coutheaderstd::endl;}std::cout***_blank_line;std::cout_body_textstd::endl;std::coutMethod: _methodstd::endl;std::coutURL: _urlstd::endl;std::coutVersion: _versionstd::endl;for(auto header_kv:_headers_kv){std::cout header_kv.first : header_kv.second std::endl;}}~HttpRequest() {} private:// 请求的基本格式std::string _req_line;std::vectorstd::string _req_handers;std::string _blank_line;std::string _body_text;//具体属性std::string _method;std::string _url;std::string _path;std::string _suffix; // 资源后缀std::string _version;std::unordered_mapstd::string,std::string _headers_kv; };class HttpResponse { public:HttpResponse():_version(httpversion),_blank_line(base_sep){}void AddCode(int code,const std::string desc){_status_codecode;_descdesc;}void AddHeader(const std::string k,const std::string v){_headers_kv[k]v;}void AddBodyText(const std::string body_text){_resp_body_textbody_text;}std::string Serialize(){// 构建状态行_status_line_versionspacesepstd::to_string(_status_code)spacesep_descbase_sep;// 构建应答报头for(auto hander:_headers_kv){std::string header_linehander.firstline_sephander.secondbase_sep;_resp_handers.push_back(header_line);}// 空行和正文// 空行已经初始化正文已经保存在_resp_body_text中// 正式序列化std::string responsestr_status_line;for(auto line:_resp_handers){responsestrline;}responsestr_blank_line;responsestr_resp_body_text;return responsestr;}~HttpResponse(){}private:// 基本属性std::string _version;int _status_code;std::string _desc;std::unordered_mapstd::string,std::string _headers_kv;// 响应的基本格式std::string _status_line;std::vectorstd::string _resp_handers;std::string _blank_line;std::string _resp_body_text; };using func_tstd::functionHttpResponse(HttpRequest);class HttpServer { private:std::string GetFileContent(const std::string path){std::ifstream in(path,std::ios::binary);if(!in.is_open()) return std::string();in.seekg(0,in.end);int filesizein.tellg(); //读写偏移量,计算文件大小in.seekg(0,in.beg);std::string content;content.resize(filesize);in.read((char*)content.c_str(),filesize);in.close();return content;}public:HttpServer(){_mime_type.insert(std::make_pair(.html,text/html));_mime_type.insert(std::make_pair(.jpg,image/jpeg));_mime_type.insert(std::make_pair(.png,image/png));_mime_type.insert(std::make_pair(.default,text/html));_code_to_desc.insert(std::make_pair(100,Continue));_code_to_desc.insert(std::make_pair(200,OK));_code_to_desc.insert(std::make_pair(201,Created));_code_to_desc.insert(std::make_pair(301,Moved Permanently));_code_to_desc.insert(std::make_pair(302,Found));} // #define TESTstd::string HandlerHttpRequest(std::string reqstr) //reqstr被客户序列化过{ #ifdef TESTstd::cout------------------------------------------------------std::endl;std::coutreqstr;std::string responsestr HTTP/1.1 200 OK\r\n;responsestr Content-Type: text/html\r\n;responsestr \r\n;responsestr htmlh1hello Linux, hello gwj!/h1/html;return responsestr;#elsestd::cout --------------------------------------- std::endl;std::cout reqstr;std::cout --------------------------------------- std::endl;HttpRequest req;HttpResponse resp; req.Deserialize(reqstr);// req.Method();if(req.Path()wwwroot/redir){std::string reire_pathhttps://www.qq.com;resp.AddCode(302,_code_to_desc[302]);resp.AddHeader(Location,reire_path);}else if (!req.GetRequestBody().empty()){if(IsServiceExists(req.Path())){resp_service_lists[req.Path()](req);}}else{std::string content GetFileContent(req.Path());if (content.empty()){content GetFileContent(wwwroot/404.html);resp.AddCode(404, _code_to_desc[404]);resp.AddHeader(Content-Length, std::to_string(content.size()));resp.AddHeader(Content-Type, _mime_type[.html]);resp.AddBodyText(content);}else{resp.AddCode(200, _code_to_desc[200]);resp.AddHeader(Content-Length, std::to_string(content.size()));resp.AddHeader(Content-Type, _mime_type[req.Suffix()]);resp.AddBodyText(content);}}return resp.Serialize();#endif}void InsertService(const std::string servicename,func_t f){std::string sprefixpathservicename;_service_lists[s]f;}bool IsServiceExists(const std::string servicename){auto iter_service_lists.find(servicename);if(iter_service_lists.end()) return false;else return true;}~HttpServer() {}private:std::unordered_mapstd::string,std::string _mime_type;std::unordered_mapint,std::string _code_to_desc;std::unordered_mapstd::string,func_t _service_lists; };
http://www.tj-hxxt.cn/news/231718.html

相关文章:

  • 做教育网站wordpress怎么换空间
  • 企业电子商务网站建设规划方案帝国+只做网站地图
  • 网站建设方案预计效果中国网站备案取消
  • 浏览网站内下载文件域名注册的网址
  • 大型门户网站建设功能小程序建站网站
  • 直播网站开发费建网站需成本多少钱
  • 网站可以制作ios用vue开发好看的官网
  • 网站图片上传代码基本型电商网站举例
  • 公司网站404wordpress安装出现eof
  • 湖南网站建设公司磐石网络商业网站策划书模板范文
  • 重庆高端网站seowordpress管理工具
  • 中国做网站最好的楼市最新消息:2023年房价走势
  • 企业网站内容建筑网校培训机构排名
  • 计生网站生育文明建设蓝色经典网站
  • 棋牌网站建设源码什么是网站设计与建设
  • 东莞网络建站别人盗用我的网站备案号怎么办
  • 聊城建设银行网站微信网站入口
  • 网站制作工作室制作平台中国机械加工行业的现状
  • 南宁网站建设索q.479185700网站手机自动跳转
  • 如何推广自己的个人网站呢企业网站是如何做的
  • 淘宝客推广网站建设网络营销外包公司招聘
  • 建立一个网站用英语怎么说老板网人才招聘
  • 临沧网站建设c3sales大型网站建设用什么系统好
  • 浙江网站建设公司电话集团网站建设基础方案
  • 奢侈品商城网站建设wordpress整合dplayer插件
  • 网站后台全能模板wordpress文章页面没有格式调整
  • 新媒体与网站建设徐州建立网站
  • 医院设计网站建设阿里云服务器做网站安全吗
  • 学院网站建设实例什么网站可以做投资
  • 国内手机网站建设企业安全文化的建设方案