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

网站换域名seo朋友圈广告怎么投放

网站换域名seo,朋友圈广告怎么投放,关键词有哪些?,中山网站建设文化渠道文章目录 前言一、了解HTTP协议是如何规定的总结 前言 HTTP协议#xff08;超文本传输协议#xff09;和我们上一篇写的网络版计算器中自己定制的协议一样#xff0c;只不过Http协议是是一个非常好用的协议#xff0c;所以我们可以直接用现成的不用自己再搞一套了。 一、了… 文章目录 前言一、了解HTTP协议是如何规定的总结 前言 HTTP协议超文本传输协议和我们上一篇写的网络版计算器中自己定制的协议一样只不过Http协议是是一个非常好用的协议所以我们可以直接用现成的不用自己再搞一套了。 一、了解HTTP协议是如何规定的 如下图所示HTTP协议包含以下几个部分 现在我们随便看一下http网址几乎都没有登录信息了因为这个东西不再被需要了。为什么http要有文件路径呢因为我们的网页资源实际上是从服务器的某个文件拿的这也就解释了为什么http协议被称为超文本传输协议。 urlencode和urldecode 像 / ? : 等这样的字符 , 已经被 url 当做特殊意义理解了 . 因此这些字符不能随意出现 . 比如 , 某个参数中需要带有这些特殊字符 , 就必须先对特殊字符进行转义 . 转义的规则如下 : 将需要转码的字符转为 16 进制然后从右到左取 4 位 ( 不足 4 位直接处理 ) 每 2 位做一位前面加上 % 编码成 %XY格式。 下面我们举个例子 wd就是我们 输入的关键字可以看到c中的号被转移为“%2B”而urldecode就是urlencode的逆过程。 首先一般情况下对于以上编码解码的过程是不需要我们做这个工作的即使需要我们做这个工作也可以直接从网络拿取写好的编码解码代码。下面我们认识一下http版本的请求和回应都有哪几部分组成 我们http请求包括请求行请求报头空行和请求正文。在请求行中我们分为三部分get是http获取的方法主要有get和post方法。url就是域名部分后面httpversion就是我们http的版本号注意后面有\r\n 比如上面红色部分就是url了。了解了请求行后我们再看请求报头每一个请求报头都由\r\n作为结尾。请求报头过来是空行空行就是\r\n然后是请求正文请求正文是可以没有的这点要注意。 在响应部分有状态行响应报头空行响应正文。状态行中分为三部分第一部分是HTTP协议版本号第二部分是状态码比如我们经常遇到的404就是状态码第三部分是状态码描述状态码描述就比如404后面跟着“访问的资源不存在”这句话。 下面我们来关注两个细节 在http中如何保证请求和响应应用层完整读取完毕了呢其实很简单我们会发现所有http请求的字段都是字符串并且以行为单位所以要保证完整读取就只需要用while循环按行为单位将所有请求行和请求报头读取完毕即可注意我们第三部分就是空行这就是while循环的判断条件只要读到空行说明我们将请求行和请求报头都读取完毕了那么如何保证读取正文呢还记得我们实现网络版计算器自定协议为正文长度\r\n正文\r\n吗没错http中报头前面也是正文的长度只要我们读取完头就知道了正文长度从而将正文读取完毕。 第二个细节 请求和响应是如何做到序列化和反序列化的这里是http自己实现的序列化只需要将请求报头按照\r\n依次插入到请求行的后面即可反序列化直接按照\r\n将整个字符串拆解为多个字符串即可。对于正文是不用做处理的这是http协议规定的。 下面我们自己构建一个简单的http服务器 首先服务器还是之前Tcp的代码我们修改一下即可 namespace server {enum{SOCKET_ERR 2,USE_ERR,BIND_ERR,LISTEN_ERR};static const uint16_t gport 8080;//listen的第二个参数是底层全连接长度1static const int gbacklog 5;class HttpServer{public:HttpServer(func_t func,const uint16_t port gport):_port(port),_listensock(-1),_func(func){}void initServer(){//1.创建文件套接字对象_listensock socket(AF_INET,SOCK_STREAM,0);if (_listensock-1){exit(SOCKET_ERR);}//2.进行bindstruct sockaddr_in local;bzero(local,sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY; //INADDR_ANY绑定任意地址IPif (bind(_listensock,(struct sockaddr*)local,sizeof(local))0){exit(BIND_ERR);}//3.Tcp需要将套接字状态设为listen状态来一直监听因为Tcp是面向字节流的)if (listen(_listensock,gbacklog)0){exit(LISTEN_ERR);}}void start(){//忽略17号信号signal(SIGCHLD,SIG_IGN);for (;;){struct sockaddr_in peer;socklen_t len sizeof(peer);int sock accept(_listensock,(struct sockaddr*)peer,len);if (sock0){continue;}coutsock: sockendl;pid_t id fork();if (id0){close(_listensock);close(sock);exit(0);} close(sock);}}~HttpServer(){}private: int _listensock; //不是用来进行数据通信的它是用来监听链接到来获取新链接的uint16_t _port;func_t _func;}; } 因为我们是没有写对客户端的请求做处理的回调函数的所以我们先写一个回调函数 因为回调函数是需要客户端请求处理后将结果返回到响应的所以还需要一个类来保存请求与响应 class HttpRequest { public:HttpRequest(){}~HttpRequest(){} public:string inbuffer; };class HttpResponse { public:string outbuffer; }; 目前我们就仅在这两个类中放一个string缓冲区即可然后我们用包装器定义一个回调函数 注意在服务器的私有成员变量中加一个回调函数然后我们在启动服务器的时候处理这个请求 下面我们编写一下处理客户端请求的函数 注意我们编写网络版计算器的时候那个时候接收客户端消息需要自己去掉报头然后反序列化而今天的实现我们就不去做那些事情因为我们只是演示一下http服务器的原理对于协议就不再浪费时间了 void HanderHttp(int sock){//1.读到完整的数据请求// ..........HttpRequest req;HttpResponse resp;char buffer[4096];ssize_t n recv(sock,buffer,sizeof(buffer)-1,0);if (n0){buffer[n] 0;req.inbuffer buffer;_func(req,resp);send(sock,resp.outbuffer.c_str(),resp.outbuffer.size(),0);}} 我们今天要做的只需要构建请求与响应对象然后定义一个缓冲区将文件描述符的数据读到缓冲区中如果读取成功我们就将缓冲区的数据放到请求对象的缓冲区中然后用回调函数对客户端的请求做处理处理完发送回客户端即可。 有了hander方法我们就可以实现一下.cc文件 void Usage(string proc) {coutUsage: \n\tproc port\r\n\r\n; } // 1.服务器和网页分离html // 2.url - / :web根目录 bool Get(const HttpRequest req,HttpResponse resp) {cout------------------http start-----------------------endl;coutreq.inbufferendl;cout------------------http end-----------------------endl;return true; } int main(int argc,char* argv[]) {if (argc!2){Usage(argv[0]);exit(0);}uint16_t port atoi(argv[1]);unique_ptrHttpServer hps(new HttpServer(Get,port));hps-initServer();hps-start();return 0; } 对于get方法我们就先演示一下等会再添加内容 下面我们运行起来 运行起来后我们该如何访问呢只需要在网址栏填入你的云服务器ip地址和端口号注意ip地址和端口号以英文冒号连接 虽然我们的网页什么都没有但是服务端会显示哪个浏览器访问我们服务端的记录下面我们解释一下每一行的意思 第一个get表示浏览器请求的方法默认的方法就是get方法。get后面的/就是url因为我们登录浏览器的时候只是告诉浏览器去哪个ip和端口并没有添加路径告诉浏览器我们要请求哪个资源所以默认是个根目录注意没有请求指定的资源默认返回服务器首页但是我们没有做处理所以是根目录。第三个HTTP1.1就是目前主流的http版本。第二行的host代表什么呢host代表我们的请求是要发送给哪个服务端的其实就是我们刚开始输入网址的ip和端口号为什么会有这个呢因为有代理服务器的存在。第三行代表支持长连接第四行代表协议升级也就是说http协议是可以被升级的。第五行就很有意思了比如你用手机浏览器登录这个网址那么上面就会显示你手机的信息如下图 看到了这个我们就不难理解为什么我们用苹果手机和安卓手机搜索一个应用程序时苹果手机浏览器会默认把ios版APP放到首页因为当我们请求某个服务器时我们用什么设备请求的信息也会被服务器拿到。第六行代表客户端能接受什么样的格式就比如文档格式第七行表示客户端支持压缩。 因为上面中是没有服务器对于客户端请求的响应的所以下面我们设计一下响应让服务端给客户端发一个我们设定好的状态行除了状态行还有空行和正文对于响应报头我们就先不写。 bool Get(const HttpRequest req,HttpResponse resp) {cout------------------http start-----------------------endl;coutreq.inbufferendl;cout------------------http end-----------------------endl;string respline HTTP/1.1 200 OK\r\n; //响应行string respblank \r\n; //空行 先暂时不写响应报头string body html lang\en\headmeta charset\UTF-8\meta name\viewport\ content\widthdevice-width, initial-scale1.0\titlemy web/titleh1hello this is test/h1/headbodyp给你科普一下鸭子的种类、达克鸭、小黄鸭、扁嘴鸭、我想你了鸭/p/body/html;resp.outbufferrespline;resp.outbufferrespblank;resp.outbufferbody;return true; } 首先说一下这样做的原理因为未来读到客户端的请求我们会调用get函数而我们上面是直接将resp填充了一下在响应中包含响应行空行和正文回调函数结束会将这个填充好的响应发送到客户端下面我们运行起来看看 可以看到我们访问这个服务器是可以看到响应的下面我们看看访问信息 可以看到是没有问题的这里我们说一下实际上我们的浏览器已经非常智能了我们刚刚没有报头的信息没有正文的长度浏览器依旧可以识别但是今天我们只是为了做演示如果真的要实现这些要做的工作我们还是需要做的。 下面我们就将报头加入进来: bool Get(const HttpRequest req,HttpResponse resp) {cout------------------http start-----------------------endl;coutreq.inbufferendl;cout------------------http end-----------------------endl;string respline HTTP/1.1 200 OK\r\n; //响应行string respheader Content-type: text/html\r\n; //响应报头string respblank \r\n; //空行 string body html lang\en\headmeta charset\UTF-8\meta name\viewport\ content\widthdevice-width, initial-scale1.0\titlemy web/titleh1hello this is test/h1/headbodyp给你科普一下鸭子的种类、达克鸭、小黄鸭、扁嘴鸭、我想你了鸭/p/body/html;resp.outbufferrespline;resp.outbufferrespheader;resp.outbufferrespblank;resp.outbufferbody;return true; } content-type代表我们有效载荷的类型通过content-type对照表我们可以告诉客户端我们返回的是什么资源比如照片就是jpg等类型然后我们在响应的缓冲区中加上响应报头。我们今天演示就以html为例 网页资源对应的就是text/html,下面我们运行起来 我们通过telnet工具可以看到响应的信息都有了。前面我们说了当我们直接以ip端口号的方式连接服务器时默认资源路径是根目录那么今天我们想访问其他其他资源该怎么做呢 我们发现当用路径去访问服务器的某个资源的时候浏览器给服务器发送的url中自动在根目录的后面加了我们要访问资源的路径下面我们实现一下这个操作并且解决两个问题1.服务器和网页分离2.url是一个/的时候表示web根目录我们也实现一下这个根目录。 首先要将服务器和网页分离那么就需要对url做切分所以我们再创建一个新文件用来处理字符串的切分 在处理url之前我们还要对请求行做拆分这样才能拿到url所以我们在请求类中在多加几个成员变量分别代表请求行请求方法url和httpversion. const string sep \r\n; class HttpRequest { public:HttpRequest(){}~HttpRequest(){}void parse(){// 1.从inbuffer中拿到第一行分隔符\r\nstring line Util::getOneLine(inbuffer,sep);if (line.empty()){return;}//2.从请求行中提取三个字段}public:string inbuffer;string method; //请求行get方法string url; //请求行urlstring httpversion; //http版本 }; 在对请求行做拆分之前还要拿到请求的第一行所以我们需要写一个函数这个函数就放在刚刚创建的新文件中因为要频繁的用到分隔符所以我们直接定义了一个。 class Util { public:static std::string getOneLine(std::string buffer,const std::string sep){auto pos buffer.find(sep);if (posstd::string::npos){return ;}std::string str buffer.substr(0,pos);buffer.erase(0,str.size()sep.size());return str;} }; 要拿到第一行还是比较简单的我们写静态成员函数的原因是不需要this指针如果是成员函数还会多一个this指针的参数并且我们未来可能会持续获取请求行请求报头用静态的会更好。要获取一行首先需要一个缓冲区然后是分隔符。这个缓冲区就是整个请求序列有请求行请求报头什么的。我们先找第一个\r\n的位置这样就确定了第一行然后判断能否找到找不到就返回一个空字符串找到了就把第一行的字符串返回并且将缓冲区第一行的字符串清空这样我们如果要获取后面的每一行就会很方便。 void parse(){// 1.从inbuffer中拿到第一行分隔符\r\nstring line Util::getOneLine(inbuffer,sep);if (line.empty()){return;}//2.从请求行中提取三个字段coutline: lineendl;stringstream ss(line);ssmethodurlhttpversion;} 获取到第一行后我们先打印然后用stringstream将以空格为分割的三个字段全部传入类内部的method和url和httpversion这里的stringstream的工作实际上就是反序列化。 在hander方法中我们先打印获取请求行的三个字段然后再调用回调函数处理。 bool Get(const HttpRequest req,HttpResponse resp) {cout------------------http start-----------------------endl;coutreq.inbufferendl;coutmethod: req.methodendl;couturl: req.urlendl;couthttpversion: req.httpversionendl;cout------------------http end-----------------------endl;//........................ } 然后我们把请求类中三个字段在执行get函数的时候打印出来后面的代码都一样就用...省略了下面我们将程序运行起来 这样我们不就把请求行和请求行的三个字段拿出来了吗当然我们也试试不加路径默认访问是什么样的请求 可以看到如果不加路径默认的请求行后面是/favicon.ico,其实这个就是我们网站的一个标签而已 如上图百度额logo就是/favicon.ico。 了解了上面的知识我们再来看看web根目录我们通过上面的图片可以看到不管服务器收到什么样的请求在url中都是以/开头的所以我们定义默认路径的时候后面不用加/ const string default_root wwwroot; //web根目录 然后我们在vscode中也创建一个这样的目录 接下来我们在请求行中增加一个string对象来保存路径 void parse(){// 1.从inbuffer中拿到第一行分隔符\r\nstring line Util::getOneLine(inbuffer,sep);if (line.empty()){return;}//2.从请求行中提取三个字段coutline: lineendl;stringstream ss(line);ssmethodurlhttpversion;//3.添加web默认路径path default_root;pathurl;if (path[path.size()-1]/){pathhome_page;}} 首先我们让路径默认是在wwwroot这个目录下然后如果用户指定路径比如在/z/b中那么路径就变成了/wwwroot/z/b所以我们让path加等url最后为什么要判断一下呢这是因为我们的用户有可能只通过ip和端口号访问他们不知道服务器的哪个路径有资源所以我们应该设置一个判断如果用户没有输入路径那么由url自动添加/的特性我们直接判断路径字符串最后一个字符是否是/如果是则说明用户没有填写路径这个时候我们就直接跳到主页即可对于主页我们也要设置一个默认文件 一般主页的默认文件都是index.html 这样的话如果用户没有指定访问路径我们就在web根目录后面添加主页文件路径这样的话就可以直接跳到主页了所以我们还应该创建一个主页的文件 然后我们就随便写一句话就好 然后我们在get函数中把路径也打印出来 下面我们运行起来看看 当url为/的时候路径会默认拼接变成wwwroot/index.html当url为指定路径的时候 通过以上的结果我们应该可以认识到web根目录是什么了下一篇文章中我们将在web根目录中写一些具体的资源并且还会加入跳转的按钮。  总结 这篇文章中主要讲解http协议是如何实现的以及底层的一些原理是什么在我们手动实现一些原理的时候我们才能对http有更加深刻的认识。
http://www.huolong8.cn/news/77253/

相关文章:

  • WordPress网站子目录访问大连建网站电话
  • 用花生棒做网站快吗512内存做网站
  • 网站500制作网页应该用哪个
  • 网站建设策划书5000字网站自助建设
  • 12306网站开发笑话专业网站建设电话
  • 网站数据分析建设做毕设网站多少钱
  • 类似于微博网站怎么做西双版纳傣族自治州海拔多少
  • 网站域名备案证书想接外包做网站
  • wap网站开发平台太平洋电脑网站
  • 网站HTML怎么做链接wordpress excel搜索功能
  • access数据库网站绿色环保材料网站模板
  • 龙胜网站建设公司Wordpress排名插件
  • 电影网站做淘宝联盟宁夏建设技术职业学院官方网站
  • 烟台市政建设招标网站建设银行官网首页登录入口
  • 图片网站怎么做优化wordpress 二次开发教程
  • 网站建设西安哪里好做汽车精品的网站
  • 英文网站推广服务合肥金融网站开发
  • 公司开发个网站青州营销型网站建设
  • 辽宁食品 中企动力网站建设服务器 无法访问网站
  • 手机小游戏网站某鲜花网站的数据库建设
  • 做百度企业网站江都微信网站建设
  • 贵安新区网站建设推广yy直播赚钱吗
  • 湛江市工程建设领域网站站长工具域名查询社区
  • 黑龙江建筑职业技术学院招生网站wordpress模板中文版
  • h5个人博客网站模板深圳手机商城网站设计多少钱
  • 单位网站建设服务广东知名网站
  • 做不做生意都要知道的网站玉溪的网站建设公司
  • 网站免费推广平台有哪些闵行网络推广公司
  • 博物馆网站建设必要企业服务网站制作
  • 网站开发语言格式化标记语言wordpress 应用模板