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

河南外贸网站建设推广普通话的方针

河南外贸网站建设,推广普通话的方针,天津市建筑信息平台,wordpress幻灯片的调用代码目录 1. HTTP协议介绍 1.1 URL介绍 1.2 urlencode和urldecode 1.3 HTTP协议格式 1.4 HTTP的方法和报头和状态码 2. 代码验证HTTP协议格式 HttpServer.hpp 2.2 html正式测试 Util.hpp index.html 2.3 再看HTTP方法和报头和状态码 2.3.1 方法_GET和POST等 2.3.2 报头…目录 1. HTTP协议介绍 1.1 URL介绍 1.2 urlencode和urldecode 1.3 HTTP协议格式 1.4 HTTP的方法和报头和状态码 2. 代码验证HTTP协议格式 HttpServer.hpp 2.2 html正式测试 Util.hpp index.html 2.3 再看HTTP方法和报头和状态码 2.3.1 方法_GET和POST等 2.3.2 报头_Cookie和Session等 2.3.3 状态码_重定向等 2.3.4 代码演示 本篇完。 1. HTTP协议介绍 网络部分到目前为止基本socket通信写完包括tcp和udp的网络通信。 学了一般的服务器设计原则和方式还有自定义协议 序列化和反序列化。 此篇写的协议是应用层的协议你在写的同时别人有没有可能写肯定有这样一来就会存在很多个人写的不同的应用层协议。 所以已经有大佬针对常见的应用场景早就写好了常见的协议软件供我们使用。 hhtp/https就属于这些写好了的常见软件。 HTTPHypertext Transfer Protocol 超文本传输协议 HTTPSHypertext Transfer Protocol Secure 超文本传输安全协议 http做的事情和我们前面做的事情是一样的包括 接收完整报文并且去掉报头。有效载荷反序列化。用户使用结构化数据执行任务。将结构化数据序列化成字符串。给有效载荷增加报头。发生完整报文。 虽然我们现在不知道它是如何实现的但毫无疑问http协议肯定比我们写的复杂而且也更加好用所以之后我们也不用再自己写了直接用现成的就可以。 又是这张图在OSI模型中网络可以分为七层而在TCP/IP模型中网络分为五层这是将OSI中的上三层包括会话层表示层应用层归为了一层统称为应用层。 前面写的网络版计算机中一共也是分为三层 底层网络连接为一层包括class TcpServer类中的所有成员。这一层对应对应OSI中的会话层。在CalClient.cc的while循环里面的步骤为一层这一层专门用来处理网络中的数据的。对应OSI中的表示层。具体的计算函数calculator为一层它在表示层被回调执行真正的业务逻辑。对应OSI中的应用层。 从上图中可以看到http就位于TCP\IP模型中的应用层所以OSI模型中的上三层工作http也会做也就是上面列举的进行序列化和反序列化等六个内容。 1.1 URL介绍 平时我们俗称的“网址”其实就是说的URL。 上图所示是一个早期使用http协议的网址以及它隔断字符的意思现在只是见一见不作讲解。 如上图所示的URL是本博客主页的网址。 目前大多使用的协议是https协议对比上面http协议的URL发现没有了端口号这是因为端口号都默认了使用http协议的进程端口号是80。使用https协议的进程端口号是443。 域名经过域名解析以后就变成了IP地址所以域名本质上就是一个IP地址用来标识一台网络主机的唯一性。有IP地址有端口号就已经能标识一个进程在网络中的唯一性了。 域名后面的/不要理解为我们Linux机器上的根目录它是web根目录也就是说这个根目录是被指定的可以是任意一个文件夹。 根目录后面的是文件路径这个路径下放的就是客户端想要的东西网络请求就是客户端将数据从服务器的这个路径下拿走。 我们平时从网上看到的图片视频音频等等网络资源都放在服务器的磁盘上。 而http协议也可以从服务器拿下来对应的网络资源这些资源都可以看作是资源文件(本质上也就是文件)又因为服务器上资源种类繁多但是http都能搞定所以http被叫做超文本传输协议。 1.2 urlencode和urldecode 看上面贴的博客网址 如上图所示的url(网址)里面包含有/以及?等字符。 像这样的字符已经被url当做特殊意义理解了因此这些字符不能随意出现。 如果url中要包含这些特殊意义的字符就需要对其做转义处理就类似C语言中的转义字符一样。但是这里是网络转义的规则不和C语言一样它有自己的规则取出字符的ASCII码 转成16进制然后前面加上百分号即可。 比如号被转义后成为%2B这个过程就叫做encode而将%2B转回到号就叫做decode。 这个过程并不需要我们自己去做有需要进行编码和解码的需求在网上直接查就可以UrlEncode编码/UrlDecode解码 - 站长工具 (chinaz.com) 如上图将字符C进行urlencode后的结果是C%2B%2B同样也可以进行urldecode进行解码。 百度一下C就是这样的网址 看到wdC%2B%2B其中wd表示关键字号后面的内容就是encode后的结果。 当服务器收到url请求后会自行对特殊字符%xx进行decode。包括汉字也需要进行encode和decode。 1.3 HTTP协议格式 HTTP是基于请求和响应的应用层协议使用的是TCP套接字客户端向服务端发送request请求服务端收到请求后会作response响应返回给客户端。 如上图所示是HTTP协议的宏观格式包括客户端的request和服务端的response。 客户端 请求行 如上图红色框中所示包含GET方法url还有http协议的版本如http/1.0或者http/1. 1这三部分构成请求行必须使用\r\n来结束这一行。 请求报头 如上图绿色框中所示包含的都是请求属性采用的是键值对的形式name表示属性的名称如HOST等value是属性的内容如具体的一个网址。每一个属性必须以\r\n来结束。 空行 如上图紫色框中所示这一行什么内容都没有只有\r\n用来表示空行。 请求正文 如上图最下面的黑色框中所示包含请求的正文如username用户名passwd密码等同样每个正文后面必须以\r\n来结束。 正文可以省略不写但是其他三部分必须有以空行为界空行后面的是请求正文空行前面的是请求行和请求报头。 每一部分都是以字符串形式放在报文中如GET url http/1.0\r\nname: value\r\n\r\n这一个报文中包含请求行一行属性以及空行。 请求行和请求报头两部分可以看成我们自定义协议中的报头请求正文是有效载荷。 服务端 状态行 如上图红色框中所示包含http/1.1HTTP协议版本状态码以及状态码描述最后是\r\n。 响应报头 如上图绿色框中所示包含响应属性和request的请求报头类似。 空行 如上图紫色框中所示也是只有一个\r\n。 响应正文 如上图黑色框中所示包含服务器要给客户端返回的数据内容如html/css/js以及图片视频音频等网络资源。 和客户端类似状态行和响应报头同样类似我们自定义协议中的报头响应正文是有效载荷。 服务端的response和客户端的request格式相同只是每一块的内容有所差异。 应用层怎么保证完整的读取了一个请求或者响应 0首先肯定可以完整的读完一行因为每一行都是以\r\n结尾的所以使用while(完整读取一行)的循环可以读完请求行请求报头直到空行再停止。 按照我们自定义协议中的逻辑此时报头(请求行请求报头)完全读完了还剩下有效载荷(请求正文)。同样地在请求报头中有一个属性Content-Length:XXX正文长度根据这个正文长度就可以将所有的请求正文读取完毕。 此时一个完整的请求request就读取到了同样的方式也可以读取到一个完整的响应response。 请求和响应是怎么做到序列化和反序列化的 序列化和反序列化是由HTTP自己实现的因为协议中的内容都是字符串第一行(请求行/状态行) 请求/响应报头只要按照\r\n为判断条件一直循环下去就可以拼接(序列化)或者拆分(反序列化)。 正文不用进行序列化和反序列化因为它本身就是字符串根据Content-Length:XXX正文长度读取相应字节数就可以。 1.4 HTTP的方法和报头和状态码 简单看下HTTP的方法和状态码和报头下面在代码中会演示。 HTTP的方法非常多但是常用的就两种分别是GET和POST方法。   HTTP常见报头Header Content-Type: 数据类型(text/html等)Content-Length: Body的长度 Host 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上User-Agent: 声明用户的操作系统和浏览器版本信息referer: 当前页面是从哪个页面跳转过来的location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能 HTTP的状态码 在代码途中会讲解到上面的内容。 telnet链接一下百度首页用GET方法获取一下资源回车后再回车空行 此时就拿到了百度首页的资源下面一大段就是html网页。 2. 代码验证HTTP协议格式 Sock.hpp和Log.hpp仍然用之前TCP套接字写好的 Log.hpp #pragma once#include iostream #include cstdio #include cstdarg #include ctime #include string// 日志是有日志级别的 #define DEBUG 0 #define NORMAL 1 #define WARNING 2 #define ERROR 3 #define FATAL 4const char *gLevelMap[] {DEBUG,NORMAL,WARNING,ERROR,FATAL };// #define LOGFILE ./threadpool.log #define LOGFILE ./calculator.log// 完整的日志功能至少: 日志等级 时间 支持用户自定义(日志内容, 文件行文件名) void logMessage(int level, const char *format, ...) // 可变参数 { #ifndef DEBUG_SHOWif(level DEBUG) {return;} #endifchar stdBuffer[1024]; // 标准日志部分time_t timestamp time(nullptr); // 获取时间戳// struct tm *localtime localtime(timestamp); // 转化麻烦就不写了snprintf(stdBuffer, sizeof(stdBuffer), [%s] [%ld] , gLevelMap[level], timestamp);char logBuffer[1024]; // 自定义日志部分va_list args; // 提取可变参数的 - #include cstdarg 了解一下就行va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof(logBuffer), format, args);va_end(args); // 相当于apnullptrprintf(%s%s\n, stdBuffer, logBuffer);// FILE *fp fopen(LOGFILE, a); // 追加到文件// fprintf(fp, %s%s\n, stdBuffer, logBuffer);// fclose(fp); } Sock.hpp #pragma once#include iostream #include string #include cstring #include cerrno #include unistd.h #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.h #include ctype.h #include Log.hppclass Sock { private:const static int gbacklog 20; // listen的第二个参数现在先不管 public:Sock(){}~Sock(){}int Socket(){int listensock socket(AF_INET, SOCK_STREAM, 0); // 域 类型 0 // UDP第二个参数是SOCK_DGRAMif (listensock 0){logMessage(FATAL, create socket error, %d:%s, errno, strerror(errno));exit(2);}logMessage(NORMAL, create socket success, listensock: %d, listensock);return listensock;}void Bind(int sock, uint16_t port, std::string ip 0.0.0.0){struct sockaddr_in local;memset(local, 0, sizeof local);local.sin_family AF_INET;local.sin_port htons(port);inet_pton(AF_INET, ip.c_str(), local.sin_addr);if (bind(sock, (struct sockaddr *)local, sizeof(local)) 0){logMessage(FATAL, bind error, %d:%s, errno, strerror(errno));exit(3);}}void Listen(int sock){if (listen(sock, gbacklog) 0){logMessage(FATAL, listen error, %d:%s, errno, strerror(errno));exit(4);}logMessage(NORMAL, init server success);}// 一般情况下// const std::string : 输入型参数// std::string *: 输出型参数// std::string : 输入输出型参数int Accept(int listensock, std::string *ip, uint16_t *port){struct sockaddr_in src;socklen_t len sizeof(src);int servicesock accept(listensock, (struct sockaddr *)src, len);if (servicesock 0){logMessage(ERROR, accept error, %d:%s, errno, strerror(errno));return -1;}if (port)*port ntohs(src.sin_port);if (ip)*ip inet_ntoa(src.sin_addr);return servicesock;}bool Connect(int sock, const std::string server_ip, const uint16_t server_port){struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(server_port);server.sin_addr.s_addr inet_addr(server_ip.c_str());if (connect(sock, (struct sockaddr *)server, sizeof(server)) 0)return true;elsereturn false;} }; 敲个和TcpServer.hpp类似的HttpServer.hpp HttpServer.hpp #pragma once#include iostream #include signal.h #include functional #include Sock.hppclass HttpServer { public:using func_t std::functionvoid(int);private:int _listensock;uint16_t _port;Sock _sock;func_t _func;public:HttpServer(const uint16_t port, func_t func) : _port(port), _func(func){_listensock _sock.Socket();_sock.Bind(_listensock, _port);_sock.Listen(_listensock);}void Start(){signal(SIGCHLD, SIG_IGN); // 让子进程退出自动释放while (true){std::string clientIp;uint16_t clientPort 0;int sockfd _sock.Accept(_listensock, clientIp, clientPort);if (sockfd 0)continue;if (fork() 0) // 子进程处理HTTP请求{close(_listensock);_func(sockfd); // 回调处理close(sockfd);exit(0);}close(sockfd);}}~HttpServer(){if (_listensock 0)close(_listensock);} }; 这代码之前基本都写过了写个测试代码 #include iostream #include memory #include HttpServer.hppvoid HandlerHttpRequest(int sockfd) {// 1. 读取请求并打印char buffer[10240];ssize_t s recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;std::cout buffer --------------------\n std::endl; // 把请求打印出来,加点分隔符} }static void Usage(const std::string process) // 使用手册 {std::cout \nUsage: process port\n std::endl; }int main(int argc, char *argv[]) {if (argc ! 2){Usage(argv[0]);exit(0);}std::unique_ptrHttpServer httpserver(new HttpServer(atoi(argv[1]), HandlerHttpRequest));httpserver-Start();return 0; } 编译运行 此时服务器已经起来了没写客户端怎么测试呢 顺便一个网页输入xshell里的主机号加冒号再加端口号这里输入121.199.6.56:8080 绑定的端口号需要自己到自己的云服务器看看端口有没有开可以手动添加本博客常用的就是8080,8081,7070,7071等这里贴个阿里云添加教程链接【图文教程】阿里云服务器开放端口设置超详细-阿里云开发者社区 此时网页是这样的 因为我们并没有给请求任何响应不过请求已经在客户端打印出来了 打印了几次应该是浏览器请求失败又请求了几次。现在试着写一个响应这里的html知识可以去简单学一学这里只是直接下面还会自己写网页很简单这里就直接用了 void HandlerHttpRequest(int sockfd) {// 1. 读取请求并打印char buffer[10240];ssize_t s recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;std::cout buffer --------------------\n std::endl; // 把请求打印出来,加点分隔符}// 2. 试着构建一个http的响应并发送std::string HttpResponse HTTP/1.1 200 OK\r\n; // 状态行HttpResponse \r\n; // 空行HttpResponse htmlh1Hello Linux NetWork GR_C/h1/html; // 正文send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0); } Ctrl C关掉上面进程重复上面步骤 上面的请求打印已经是刷新浏览器之后的了 成功运行。 也可以用之前的 telnet 链接然后输入GET / http/1.1获取请求的第一行 2.2 html正式测试 上面打印出的请求中第一行就是请求的资源。 写一个截取请求变为子串的工具类 Util.hpp #pragma once#include iostream #include vectorclass Util { public:// aaaa\r\nbbbbb\r\nccc\r\n\r\nstatic void cutString(std::string s, const std::string sep, std::vectorstd::string *out){ // 剪切读取到的请求,static使得类名直接访问方法函数std::size_t start 0;while (start s.size()){auto pos s.find(sep, start); // 从start开始查找sep分隔符if (pos std::string::npos) // 找不到,breakbreak;std::string sub s.substr(start, pos - start); // 找到了,子串截取out-push_back(sub); // 截取到的子串push进vectorstart start sub.size() sep.size(); // 让start指向分隔符右侧,不断循环}if (start s.size()) // 后面还有内容也pushout-push_back(s.substr(start));} }; 测试一下我们的截取功能并打印 void HandlerHttpRequest(int sockfd) {// 1. 读取请求并打印char buffer[10240];ssize_t s recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;std::cout buffer --------------------\n std::endl; // 把请求打印出来,加点分隔符}std::vectorstd::string vline; // 剪切读取到的请求Util::cutString(buffer, \n, vline); // 读取第一行std::vectorstd::string vblock;Util::cutString(vline[0], , vblock); // 第一行拆开std::cout #### start ################ std::endl;for(auto iter : vblock){std::cout --- iter \n std::endl;}std::cout ##### end ############### std::endl;// 2. 试着构建一个http的响应并发送std::string HttpResponse HTTP/1.1 200 OK\r\n; // 状态行HttpResponse \r\n; // 空行HttpResponse htmlh1Hello Linux NetWork GR_C/h1/html; // 正文send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0); } 这里网页再输入121.199.6.56:7070就成功提取并打印了 ​ 如果网页输入121.199.6.56:7070/a/b/c/d.html请求的路径也成功被打印出来了 也可以发现我们前面网页输入121.199.6.56:7070请求的是/这个不叫作根目录而叫作web根目录 这里新建一个wwwroot目录在里面建一个index.html文件框架安装插件后感叹号加回车就出来了 index.html !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleTestWeb/title /head bodyh1Hello Linux NetWork GR_C html/h1phello 哈喽 这里是段落部分....../pphello 哈喽 这里是段落部分....../pphello 哈喽 这里是段落部分....../p /body /html HttpServer.cc #include iostream #include memory #include fstream #include sys/types.h #include sys/stat.h #include fcntl.h #include HttpServer.hpp #include Util.hpp// 一般http都要有自己的web根目录,下面让请求的资源从web根目录开始,这就是为什么叫作web根目录 #define ROOT ./wwwroot // ./wwwroot/index.html #define HOMEPAGE index.html // 如果客户端只请求了一个/,返回默认首页static void Usage(const std::string process) // 使用手册 {std::cout \nUsage: process port\n std::endl; }void HandlerHttpRequest(int sockfd) {// 1. 读取请求并打印char buffer[10240];ssize_t s recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;std::cout buffer --------------------\n std::endl; // 把请求打印出来,加点分隔符}std::vectorstd::string vline; // 剪切读取到的请求Util::cutString(buffer, \n, vline); // 读取第一行std::vectorstd::string vblock;Util::cutString(vline[0], , vblock); // 第一行拆开// std::cout #### start ################ std::endl;// for(auto iter : vblock)// {// std::cout --- iter \n std::endl;// }// std::cout ##### end ############### std::endl;std::string file vblock[1]; // 就是请求路径,类似/a/b/c.htmlstd::string target ROOT; // 定义成自己宏定义的web根目录if (file /) // 如果请求的是web根目录(类似默认目录)file /index.html; // 默认目录改成这个target file;std::cout target std::endl;std::string content; // 存文件内容的std::ifstream in(target); // 打开target路径文件if (in.is_open()) // 成功打开{std::string line;while (std::getline(in, line)){content line;}in.close();}std::string HttpResponse; // 构建响应,现在先简单用用 // 后面还会讲解if (content.empty()) // 状态行-没有内容{HttpResponse HTTP/1.1 301 Moved Permanently\r\n;}else // 有内容(正常){HttpResponse HTTP/1.1 200 OK\r\n;}HttpResponse \r\n; // 空行HttpResponse content; //正文// // 2. 试着构建一个http的响应并发送// std::string HttpResponse HTTP/1.1 200 OK\r\n; // 状态行// HttpResponse \r\n; // 空行// HttpResponse htmlh1Hello Linux NetWork GR_C/h1/html; // 正文send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0); }int main(int argc, char *argv[]) {if (argc ! 2){Usage(argv[0]);exit(0);}std::unique_ptrHttpServer httpserver(new HttpServer(atoi(argv[1]), HandlerHttpRequest));httpserver-Start();return 0; } 运行后网页输入121.199.6.56:7070就是这样 都和预料的一样。也可以输入121.199.6.56:7070后输入对应路径获取资源这里就不演示了。 2.3 再看HTTP方法和报头和状态码 再看下上面的知识 2.3.1 方法_GET和POST等 上面已经在 telnet链接用GET方法获取过了资源下面在代码中使用一下 这里再wwwroot下建立一个a目录在a目录里建立b目录在b目录里写一个test.html !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleTestGET/title /head bodyh1测试GET/h1phello 哈喽 这里是段落部分....../pform nameinput action/a/b/test.html methodGETUsername: input typetext nameuserbr/Password: input typepassword namepwd br/input typesubmit value登陆/form /body /html 把服务端起来然后用浏览器输入121.199.6.56:7070/a/b/test.html访问这个资源 随便输入用户名和密码然后点击登录 此时服务端拿到了用户名和密码还可以发现在网页上也显示出来了这说明GET方法是通过url向服务端传参的。 在test,html里把GET方法改成post方法大小写不敏感改成post试试 重复上面步骤 输入后点击登录是这样的url上并没有回显参数 所以POST方法是通过HTTP的正文提交参数的。 得到的结论GET方法通过url提交参数。 POST方法通过HTTP请求正文提交参数。 站在客户端的角度如果使用GET方法在提交form表单的时候内容会拼接到url中在浏览器的网址栏中可以看到如果是账号密码的话其他人就能够直接看到。 如果使用POST方法在提交form表单的时候内容是通过请求正文提交的在浏览器的网址栏中看不到。 所以如果提交的数据是比较私密的如账号密码等就使用POST方法如果无所谓的数据就使用POST/GET哪个都行。 但是并不是说POST方法比GET方法安全仅仅是POST方法无法直观的看到提交的数据。 POST/GET两种方法都是不安全的。 其它方法几乎用不到这里就不讲解了。 2.3.2 报头_Cookie和Session等 HTTP常见报头Header Content-Type: 数据类型(text/html等)Content-Length: Body的长度 Host 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上User-Agent: 声明用户的操作系统和浏览器版本信息referer: 当前页面是从哪个页面跳转过来的location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能 在使用POST方法发起HTTP请求后多了几个GET方法中没有的属性如上图所示。 Connection: close表示短连接 Connection: keep-alive表示长连接 一个客户端对应一个套接字客户端的一个请求响应完后套接字不关闭只有客户端退出了或者指定关闭时套接字才关闭。一个客户端无论有多少个请求都通过一个套接字和服务器进行网络通信。 Content-Length: XXX\r\n 使用POST方法发起请求时服务器收到的请求中就有Content-Length这一属性用来表示请求正文的长度以字节为单位。 Content-Type: xxx\r\n 表示连接类型请求和响应中都有。 上图所示的是请求中的Content-Type由于会用表单提交数据所以它的值如上图红色框中所示。这是浏览器在告诉服务器它提交的请求类型是form服务器需要按照表单的处理方式来处理。 Cookie技术 假设访问CSDN使用的是HTTP协议。 CSDN在第一次登录后之后打开CSDN就不用再进行登陆了。根据前面学习我们知道登录时输入的信息其实就是form表单然后将数据提交给服务器让服务器进行鉴权如果权限符合就会返回对应的响应。 HTTP实际上是一种无状态协议每次请求并不会记录它曾经请求了什么。 所以在第一次登录CSDN后在站内进行网页跳转从一篇文章到另一篇文章时理论上需要再次输入账号密码进行登录让服务器进行鉴权因为HTTP的每次请求/响应之间是没有任何关系的。但我们在使用浏览器访问CSDN的时候发现并不是这样的只需要登录一次即可。 这是因为浏览器在我们第一次登录CSDN的时候将我们的账号密码等登录信息保存了下来。 当我们进行网页跳转或者再次打开CSDN的时候浏览器自动将保存的用户登录信息添加到了请求报头中并通过HTTP协议发送给了服务器服务器进行鉴权并返回对应的响应。 登录还是需要的只是浏览器帮我们做了这个事。这种技术就叫做Cookie技术。 如上图所示点击网址前面的小锁可以查看当前浏览器正在使用的Cookie。 当我们将上图中和CSDN有关的Cookie数据删除后就需重新输入账号密码来登录了。 如上图所示点击网址前面的小锁可以查看当前浏览器正在使用的Cookie。 当我们将上图中和CSDN有关的Cookie数据删除后就需重新输入账号密码来登录了。 用户在第一次输入账号和密码时浏览器会进行保存Cookie近期再次访问同一个网站发送http请求浏览器会自动将用户信息添加到报头中推送给服务器。这样只要用户首次输入密码一段时间内将不用再做登录操作了。 Cookie又分为内存级和文件级 内存级Cookie将信息保存在浏览器的缓冲区中当浏览器被关闭时意味着进程结束保存的信息也就没有了重新打开浏览器后还需要重新登录。文件级Cookie将信息保存在文件中文件是放在磁盘上的无论浏览器怎么打开关闭文件中的信息都不会删除在之后发送HTTP请求时浏览器从该文件中读取信息并加到请求报头中。 根据日常使用浏览器的情况我们可以知道大部分情况下的Cookie都是文件级别的因为关闭了浏览器下次打开不用再重新登录。 Cookie文件也是存在我们电脑上的具体路径有兴趣可以去找一下。 cookie安全机制cookie下面的设置可以提高安全性 domain可以访问该Cookie的域名。如果设置为“.google.com”则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”。pathCookie的使用路径。如果设置为“/sessionWeb/”则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”。httponly如果cookie中设置了HttpOnly属性那么通过js脚本将无法读取到cookie信息这样能有效的防止XSS攻击窃取cookie内容这样就增加了cookie的安全性,但不是绝对防止了攻击secure该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPSSSL等在网络上传输数据之前先将数据加密。默认为false。expires:指定了coolie的生存期默认情况下cookie是暂时存在的他们存储的值只在浏览器会话期间存在当用户退出浏览器后这些值也会丢失如果想让cookie存在一段时间就要为expires属性设置为未来的一个过期日期。现在已经被max-age属性所取代max-age用秒来设置cookie的生存期 Set-Cookie: qwerty219ffwef9w0f; Domainsomecompany.co.uk; Path/; ExpiresWed, 30 Aug 2019 00:00:00 GMT 对保存到cookie里面的敏感信息加密设置指定的访问域名设置HttpOnly为true设置Secure为true给Cookie设置有效期给Cookies加个时间戳和IP戳实际就是让Cookies在同个IP下多少时间内失效 Session技术 如果我们电脑上的Cookie文件被不法份子盗取那么它就能以我们的身份去登录我们的CSDN并且进行一些非法操作。 为了保证信息安全新的做法是将用户的账号密码信息以及浏览痕迹等信息保存在服务器上。每个用户对应一个文件这个文件被叫做Session文件由于存在很多的Session文件所以给每个文件一个名字叫做Session id。服务器将Session id作为响应返回给用户此时用户的Cookie中保存的就是这个id值。 如上图所示当第一次登录时浏览器的form表单中的用户信息提交到了服务器服务器创建Session文件并保存用户信息然后再生成一个id返回给浏览器。 此时浏览器的Cookie保存的就是这个id值。当进行站内页面跳转或者再次打开CSDN的时候浏览器自动将Cookie中Session id加到请求报头中提交给服务端。 服务端存储用户信息的技术就叫做Session技术。 为什么新的会话保持(Cookie和Session)技术能够提高用户信息的安全性呢 服务端是由专业的人员维护的服务器中存在病毒以及流氓软件的可能想更小所以用户信息在服务端会更安全。如果客户端的Cookie中的Session id被盗用不法分子使用该id向服务端发起请求时会因为常用IP地址不一样而被服务端强制下线此时只有手里真正有账号密码的人才能够再次登录。 保证Session安全的策略非常多有兴趣可以自行了解。 2.3.3 状态码_重定向等 在构建响应的时候状态行中的状态码直接写的200状态码描述是OK。那么状态码到底有哪些呢它们代表的意义是什么 状态码有五种类型分别以1~5开头 状态码类别原因短语1XXinforma(信息性状态码)接收的请求正在处理2XXSuccess(成功状态码)请求正常且处理完毕3XXRedirection(重定向状态码)需要进行附加操作以完成请求4XXClient Error(客户端错误状态码)服务器无法处理请求5XXServer Error(服务器错误状态码)服务器处理请求出错 最常见的一些状态码如200(OK)404(Not Found)403(Forbidden请求权限不够)302(Redirect)504(Bad Gateway)。 这些状态码没什么好说的如果在代码中要用到可以去找一些比较权威的文档也可以去查一下表不过网上的表也不是每个人都遵守的不过建议大家还是遵守。 下面重点说一下重定向状态码(3XX) 看下网上的一些表 重定向就是将网络请求重新定个方向转到其它位置跳转网站此时这个服务器相当于提供了一个引路的服务。 相信都有过这样的经历打开一个网址以后自动就弹出一些广告网页这就是一种重定向。 浏览器发送请求给服务端服务端返回一个新的url并且状态码是3XX浏览器会自动用这个新的url向新地址的服务端发起请求。 所以说重定向是由客户端完成的当客户端浏览器收到的响应中状态码是3XX后它就会自动从响应中寻找返回的新的url并发起请求。 重定向又有两种 永久重定向状态码为301。临时重定向状态码为302和307。 临时重定向和永久重定向本质是影响客户端的标签决定客户端是否需要更新目标地址。 如果某个网站是永久重定向那么第一次访问该网站时由浏览器帮你进行重定向但后续再访问该网站时就不需要浏览器再进行重定向了此时直接访问的就是重定向后的网站。 而如果某个网站是临时重定向那么每次访问该网站时都需要浏览器来帮我们完成重定向跳转到目标网站。 2.3.4 代码演示 在前面写的代码加点代码演示一下 在b目录里再建一个404.html照片可以不带emmm !DOCTYPE html html langen headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title页面不存在/title /head bodyh1你访问的页面不存在/h1br/img srchttps://img-blog.csdnimg.cn/img_convert/4a13d13d43fdcd24ba8dac4c37e1e115.gif altGR_C博客里的条总 title条总 /body /html HandlerHttpRequest函数 void HandlerHttpRequest(int sockfd) {// 1. 读取请求并打印char buffer[10240];ssize_t s recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;std::cout buffer --------------------\n std::endl; // 把请求打印出来,加点分隔符}std::vectorstd::string vline; // 剪切读取到的请求Util::cutString(buffer, \n, vline); // 读取第一行std::vectorstd::string vblock;Util::cutString(vline[0], , vblock); // 第一行拆开// std::cout #### start ################ std::endl;// for(auto iter : vblock)// {// std::cout --- iter \n std::endl;// }// std::cout ##### end ############### std::endl;std::string file vblock[1]; // 就是请求路径,类似/a/b/c.htmlstd::string target ROOT; // 定义成自己宏定义的web根目录if (file /) // 如果请求的是web根目录(类似默认目录)file /index.html; // 默认目录改成这个target file;std::cout target std::endl;std::string content; // 存文件内容的std::ifstream in(target); // 打开target路径文件if (in.is_open()) // 成功打开{std::string line;while (std::getline(in, line)){content line;}in.close();}std::string HttpResponse; // 构建响应,现在先简单用用 // 后面还会讲解if (content.empty()) // 状态行-没有内容{HttpResponse HTTP/1.1 301 Moved Permanently\r\n;// HttpResponse Location: https://blog.csdn.net/GRrtx?typeblog\r\n; // 重定向HttpResponse Location: http://121.199.6.56:7070/a/b/404.html\r\n; // 站内跳转}else // 有内容(正常){HttpResponse HTTP/1.1 200 OK\r\n;HttpResponse (Content-Type: text/html\r\n); // 要识别,有些浏览器能自动识别,不过现在是网页,可以是照片和视频等HttpResponse (Content-Length: std::to_string(content.size()) \r\n);HttpResponse Set-Cookie: 这是一个cookie(小块的东西)\r\n;}HttpResponse \r\n; // 空行HttpResponse content; //正文// // 2. 试着构建一个http的响应并发送// std::string HttpResponse HTTP/1.1 200 OK\r\n; // 状态行// HttpResponse \r\n; // 空行// HttpResponse htmlh1Hello Linux NetWork GR_C/h1/html; // 正文send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0); } 服务器起来然后在浏览器输入121.199.6.56:7070访问一下 在浏览器输入121.199.6.56:7070/test404test访问一下不存在的页面 直接重定向到404.html了。 访问下a/b/test.html然后登录 此时a/b/test.html里的方法是post改成get重复上面步骤 点击登录后也会重定向到我们的404页面你也可以让它重定向到其它页面。 永久重定向无法演示出来效果和临时重定向一样。 贴下服务器上收到多个请求的原因 一个网页中有多种类型的资源而一次请求只能获取一种类型资源。虽然我们在浏览器中只访问一次但是浏览器会通过多个线程发起多次请求。多次请求的多个响应共同组成了一个网页。 本篇完。 下一篇网络和Linux网络_6应用层HTTPS协议加密解密中间人攻击证书。
http://www.hkea.cn/news/14345871/

相关文章:

  • 大网站前端怎么做的优化大师的功能有哪些
  • 网站seo 规范免费注册
  • 帝国音乐网站怎么做数据表网站做关键词首页
  • 海淀做网站好的公司中国机械制造网
  • 邢台企业做网站找谁广告推广渠道
  • 做书的网站做花生的网站
  • 湛江网站建设推广移动端 pc网站开发
  • 番禺企业网站建设美术生最吃香的专业
  • 怎么做网站网页归档常州网站建设要多少钱
  • 门户网站等保二级建设方案广东网站备案要求
  • 网站开发 英语词汇重庆网网站建设公司
  • 做网站横幅的图片多大百度浏览器官网入口
  • 织梦做网站的教程房地产销售技巧和话术
  • 深圳网站公司哪家好需要哪些技术
  • 泸州住房和城乡建设厅网站自己怎么开发app软件
  • 国内永久免费建站wordpress点击文章404
  • 做网站 侵权赣州房产网站建设
  • 网站设计书seo排名优化
  • 校园网上零售网站建设方案做电子商城网站的
  • 大连做网站大公司网站开发师是做什么的
  • 手机做网站自己做小程序ui设计
  • 怎么建设微信网站wordpress单页导航
  • 新加坡房产网站大全网站案例上海
  • 汕头市公司网站建设多少钱临淄信息港官网
  • wordpress网站入口ps海报模板素材免费
  • 做网站流量怎么解决天津网站优化哪家好
  • 临西做网站多少钱济宁建设网站制作
  • 如何用电脑做网站服务器吗h5免费制作app
  • 江门东莞网站建设小型手机网站建设哪家好
  • 在建设银行网站上还贷WordPress主题启用出现错误