HTTP(HyperText Transfer Protocol,超⽂本传输协 )的协议。
http本身没有维护连接信息,它会把数据交给传输层的TCP,当TCP建立好连接后,http直接发送数据,不关心TCP的细节
http本身无状态,不会记录用户信息
虽然我们说, 应用层协议是我们程序猿自己定的.。但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)就是其中之一。
下面我们看个常见的url:
urlencode和urldecode
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。例如:输入C++
+
被转移成了%2B
了,urldecode就是urlencode的逆过程。
urlencode工具(https://tool.chinaz.com/Tools/urlencode.aspx)
注意:
是一行一行读的
,当读到空行
时,再往下读就是正文部分
了。content-Length
,它会标识每个正文有多少字节,保证不会读到多余的正文。下面来用fildder抓包工具来抓下包试试:比如我抓个nba的
看圈起来的raw
再来看看对应的刚刚抓的包
http的版本
,状态码
,状态码描述
方法 | 说明 | 支持的 http协议版本 |
---|---|---|
GET | 获取资源 | 1.0 、1.1 |
POST | 传输实体主体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除文件 | 1.0、1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRCAE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINE | 断开的连接关系 | 1.0 |
我们常用的2中方法是GET和POST
GET 通过url来传参,长度限制
POST是通过正文来传参
类别 | 原因短语 | |
---|---|---|
1XX | Informantion(信息性状态码) | 接收的请求正在处理 |
2XX | Sucess (成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作已完成请求 |
4XX | Clinet Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器状态码) | 服务器处理请求出错 |
最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)
http是无状态的,不会记录用户的信息,则会导致用户需要一直登录,用户的体验很差。我们平时只要登录一次下次就用登录是怎么回事呢?是因为Cookie是有状态的。
客户端自一次发送请求将自己的用户名和密码发送给服务器,服务器会创建set_cookie文件,再发送回客户端的浏览器,cookie文件则保存在浏览器中。cookie的本质就是浏览器中的一个文件
有一天电脑中病毒了,cookie文件被盗了,我们和服务器的通信细节都会被别人知道了,那该怎么办呢?就要用session来处理了。
session是将敏感的信息放在服务器中,返回给客户端一个cookie sid,下次客户端返送请求,服务器通过sid找到之前的状态。注意
session是相对安全一些。
https比http多了加密和解密,http是直接将数据交给下一层,https是先交给SSL/TLS进行加密。
对称加密
对称加密用一把秘钥进行加密和解密。
这样的通信不安全,秘钥丢了就吉吉了。
非对称加密
非对称加密通常
用公钥加密
,私钥解密
。
具体流程:
为什么不直接用非对称加密通信?
非对称加密效率低,对称加密效率高。
实现一个简单的http服务器,在网页上输出hello
httpServer.hpp
1 #include<iostream>
2 #include<sys/socket.h>
3 #include<sys/types.h>
4 #include<arpa/inet.h>
5 #include<netinet/in.h>
6 #include<unistd.h>
7 #include<signal.h>
8 #define BACKLOG 5
9 using namespace std;
10
11 class httpServer
12 {
13
14 private:
15 int port;
16 int lsock;
17 public:
18 httpServer(int _port=8080,int _lsock= -1)
19 :port(_port)
20 ,lsock(_lsock)
21 {}
22 void initServer()
23 {
24 signal(SIGCHLD,SIG_IGN);
25 lsock=socket(AF_INET,SOCK_STREAM,0);
26 if(lsock < 0)
27 {
28 cerr<<"socket error"<<endl;
29 exit(2);
30 }
31 struct sockaddr_in local;
32 local.sin_family = AF_INET;
33 local.sin_port = htons(port);
34 local.sin_addr.s_addr = INADDR_ANY;
35 if(bind(lsock,(struct sockaddr*)&local,sizeof(local)) < 0)
36 {
37 cerr<<"bind error"<<endl;
38 exit(3);
39 }
40 if(listen(lsock,BACKLOG) < 0)
41 {
42 cerr<<"listen error"<<endl;
43 exit(4);
44 }
45
46 }
47 void EchoHttp(int sock)
48 {
49 char response[2048];
50 ssize_t s = recv(sock,response,sizeof(response),0);
51 if(s > 0)
52 {
53 response[s] = 0;
54 string response = "HTTP/1.0 200 OK\r\n";
55 response += "Content-type: text/html\r\n";
56
57 response += "\r\n";
58
59 response += "hello
";
60 send(sock,response.c_str(),response.size(),0);
61
62 }
63 close(sock);
64 }
65 void start()
66 {
67 struct sockaddr_in peer;
68 for(;;){
69 socklen_t len = sizeof(peer);
70 int sock = accept(lsock,(struct sockaddr*)&peer,&len);
37 cerr<<"bind error"<<endl;
38 exit(3);
39 }
40 if(listen(lsock,BACKLOG) < 0)
41 {
42 cerr<<"listen error"<<endl;
43 exit(4);
44 }
45
46 }
47 void EchoHttp(int sock)
48 {
49 char response[2048];
50 ssize_t s = recv(sock,response,sizeof(response),0);
51 if(s > 0)
52 {
53 response[s] = 0;
54 string response = "HTTP/1.0 200 OK\r\n";
55 response += "Content-type: text/html\r\n";
56
57 response += "\r\n";
58
59 response += "hello
";
60 send(sock,response.c_str(),response.size(),0);
61
62 }
63 close(sock);
64 }
65 void start()
66 {
67 struct sockaddr_in peer;
68 for(;;){
69 socklen_t len = sizeof(peer);
70 int sock = accept(lsock,(struct sockaddr*)&peer,&len);
71 if(sock < 0)
72 {
73 cerr<<"accept error"<<endl;
74 continue;
75 }
76 if(fork() == 0)
77 {
78 close(lsock);
79 EchoHttp(sock);
80 exit(0);
81 }
82 close(sock);
83 }
84 }
85 ~httpServer()
86 {
87 if(lsock != -1)
88 {
89 close(lsock);
90 }
91 }
92 };
httpServer.cc
1 #include "httpServer.hpp"
2
3 static void Usage(string proc)
4 {
5 cout << "Usage:\n\t";
6 cout << proc << " port" << endl;
7
8 }
9
10 int main(int argc ,char *argv[])
11 {
12 if(argc != 2){
13 Usage(argv[0]);
14 exit(1);
15
16 }
17
18 httpServer *hp = new httpServer(atoi(argv[1]));
19 hp->initServer();
20 hp->start();
21
22 return 0;
23
24 }
在浏览器输入ip地址:端口号