HTTP协议
在互联⽹世界中,
HTTP
(HyperText Transfer Protocol,超⽂本传输协议)是⼀个⾄关重要的协议。 它定义了客⼾端(如浏览器)与服务器之间如何通信,以交换或传输超⽂本(如HTML⽂档)。
HTTP协议是客⼾端与服务器之间通信的基础。客⼾端通过HTTP协议向服务器发送请求,服务器收到 请求后处理并返回响应。HTTP协议是⼀个
⽆连接
、
⽆状态
的协议,即每次请求都需要建⽴新的连接, 且服务器不会保存客⼾端的状态信息。
认识URL
平时我们俗称的 “网址” 其实就是这里所说的URL

urlencode
和
urldecode
像
/ ?
: 等这样的字符, 已经被
url
当做特殊意义理解了. 因此这些字符不能随意出现.
⽐如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进⾏转义.
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做⼀位,前⾯加
上%,编码成%XY格式
例如:
"+" 被转义成了 "%2B"
urldecode就是urlencode的逆过程;
认识HTTP请求与响应的格式
HTTP请求
•
⾸⾏: [⽅法] + [url] + [版本]
•
Header: 请求的属性, 冒号分割的键值对;每组属性之间使⽤ \r\n 分隔;遇到空⾏表⽰ Header
部分结束
•
Body: 空⾏后⾯的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有⼀个
Content-Length属性来标识Body的⻓度;
HTTP响应
•
⾸⾏: [版本号] + [状态码] + [状态码解释]
•
Header: 请求的属性, 冒号分割的键值对;每组属性之间使⽤\r\n分隔;遇到空⾏表⽰Header部分结
束
•
Body: 空⾏后⾯的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有⼀个
Content-Length属性来标识Body的⻓度; 如果服务器返回了⼀个html⻚⾯, 那么html⻚⾯内容就
是在body中.
基本应答格式
HTTP的⽅法

其中我们最常⽤的就是
GET
⽅法和
POST
⽅法.
GET方法(重点)
⽤途:⽤于请求URL指定的资源。
示例:
⽰例:
GET /index.html HTTP/1.1
特性:指定资源经服务器端解析后返回响应内容。
form表单:
HTML 表单 | 菜鸟教程
注意:
要通过自己写的
http
服务器,验证
GET
⽅法
,
这⾥需要了解⼀下
FORM
表单的问题
就要引⼊
web根⽬录
,⽂件读取的基本操作。
std::string GetFileContentHelper(const std::string &path)
{
// ⼀份简单的读取⼆进制⽂件的代码
std::ifstream in(path, std::ios::binary);
if (!in.is_open())
return "";
in.seekg(0, in.end);
int filesize = in.tellg();
in.seekg(0, in.beg);
std::string content;
content.resize(filesize);
in.read((char *)content.c_str(), filesize);
// std::vector<char> content(filesize);
// in.read(content.data(), filesize);
in.close();
return content;
}
POST方法(重点)
⽤途:⽤于传输实体的主体,通常⽤于提交表单数据。
⽰例:
POST /submit.cgi HTTP/1.1
特性:可以发送⼤量的数据给服务器,并且数据包含在请求体中。
同样的要使用我们自己写的HTTP服务器验证POST方法,也需要用到FORM表单;
form表单:
HTML 表单 | 菜鸟教程
PUT方法
⽤途:⽤于传输⽂件,将请求报⽂主体中的⽂件保存到请求URL指定的位置。
⽰例:
PUT /example.html HTTP/1.1
特性:不太常⽤,但在某些情况下,如RESTful API中,⽤于更新资源。
HEAD方法
⽤途:与GET⽅法类似,但不返回报⽂主体部分,仅返回响应头。
⽰例:
HEAD /index.html HTTP/1.1
特性:⽤于确认URL的有效性及资源更新的⽇期时间等。
DELETE⽅法
⽤途:⽤于删除⽂件,是PUT的相反⽅法。
⽰例:
DELETE /example.html HTTP/1.1
特性:按请求URL删除指定的资源。
OPTIONS⽅法
⽤途:⽤于查询针对请求URL指定的资源⽀持的⽅法。
⽰例:
OPTIONS * HTTP/1.1
特性:返回允许的⽅法,如GET、POST等。
HTTP的状态码
最常⻅的状态码, ⽐如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad
Gateway)
| 状态码 | 含义 | 应用样例 |
| 100 | Continue |
上传⼤⽂件时,服务器告诉客⼾端可以继续上传
|
| 200 | Ok |
访问⽹站⾸⻚,服务器返回⽹⻚内容
|
| 201 | Created |
发布新⽂章,服务器返回⽂章创建成功的信息
|
| 301 |
Moved Permanently
|
⽹站换域名后,⾃动跳转到新域名;搜索引擎更新⽹站
链接时使⽤
|
| 302 |
Found 或 See Other
|
⽤⼾登录成功后,重定向到⽤⼾⾸⻚
|
|
304
|
Not Modified
|
浏览器缓存机制,对未修改的资源返回304状态码
|
| 400 |
Bad Request
|
填写表单时,格式不正确导致提交失败
|
| 401 |
Unauthorized
|
访问需要登录的⻚⾯时,未登录或认证失败
|
| 403 |
Forbidden
|
尝试访问你没有权限查看的⻚⾯
|
| 404 |
Not Found
|
访问不存在的⽹⻚链接
|
| 500 |
Internal Server Error
|
服务器崩溃或数据库错误导致⻚⾯⽆法加载
|
| 502 |
Bad Gateway
|
使⽤代理服务器时,代理服务器⽆法从上游服务器获取
有效响应
|
| 503 |
Service Unavailable
|
服务器维护或过载,暂时⽆法处理请求
|
重定向
相关状态码的表格:
| 状态码 | 含义 | 是否为临时重定向 | 应用样例 |
| 301 |
Moved Permanently
|
否(永久重定向)
|
⽹站换域名后,⾃动跳转
到新域名;搜索引擎更新
⽹站链接时使⽤
|
| 302 |
Found 或 See Other
|
是(临时重定向)
|
⽤⼾登录成功后,重定向
到⽤⼾⾸⻚
|
| 307 |
Temporary Redirect
|
是(临时重定向)
|
临时重定向资源到新的位
置(较少使⽤)
|
| 308 |
Permanent Redirect
|
否(永久重定向)
|
永久重定向资源到新的位
置(较少使⽤)
|
关于重定向的验证,以301为代表
HTTP状态码301(
永久重定向
)和302(
临时重定向
)都依赖Location选项。以下是关于两者依赖
Location选项的详细说明:
HTTP状态码
301
(永久重定向)
•
当服务器返回HTTP 301状态码时,表⽰请求的资源已经被永久移动到新的位置。
•
在这种情况下,服务器会在响应中添加⼀个Location头部,⽤于指定资源的新位置。这个Location 头部包含了新的URL地址,浏览器会⾃动重定向到该地址。
•
例如,在HTTP响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\n
HTTP状态码
302
(临时重定向)
•
当服务器返回HTTP 302状态码时,表⽰请求的资源临时被移动到新的位置。
•
同样地,服务器也会在响应中添加⼀个Location头部来指定资源的新位置。浏览器会暂时使⽤新的 URL进⾏后续的请求,但不会缓存这个重定向。
•
例如,在HTTP响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n
总结:⽆论是HTTP 301还是HTTP 302重定向,都需要依赖Location选项来指定资源的新位置。这个
Location选项
是⼀个标准的HTTP响应头部,⽤于告诉浏览器应该将请求重定向到哪个新的URL地址。
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服务器
实现⼀个最简单的HTTP服务器, 只在⽹⻚上输出 "hello world"; 只要我们按照HTTP协议的要求构造数据,就可以得到。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Usage() {
printf("usage: ./server [ip] [port]\n");
}
int main(int argc, char* argv[]) {
if (argc != 3) {
Usage();
return 1;
}
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0) {
perror("bind");
return 1;
}
ret = listen(fd, 10);
if (ret < 0) {
perror("listen");
return 1;
}
for (;;) {
struct sockaddr_in client_addr;
socklen_t len;
int client_fd = accept(fd, (struct sockaddr*)&client_addr, &len);
if (client_fd < 0) {
perror("accept");
continue;
}
char input_buf[1024 * 10] = {0}; // ⽤⼀个⾜够⼤的缓冲区直接把数据读完.
ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);
if (read_size < 0) {
return 1;
}
printf("[Request] %s", input_buf);
char buf[1024] = {0};
const char* hello = "<h1>hello world</h1>";
sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello),
hello);
write(client_fd, buf, strlen(buf));
}
return 0;
}
编译, 启动服务. 在浏览器中输⼊ http://[ip]:[port], 就能看到显⽰的结果 "Hello World"
今天的内容分享就到这里,欢迎各位大佬来评论区指点。
1047

被折叠的 条评论
为什么被折叠?



