前言
前面我们把 TCP 三次握手、四次挥手、TIME_WAIT、UDP 套接字编程 全部学完了,TCP/UDP 属于传输层协议。
实际上网、浏览器访问网页、接口调用、前后端交互,底层都是 TCP,上层跑的就是 HTTP 协议。
本节课重点:搞懂 HTTP 是什么、请求报文、响应报文、请求方法、状态码、HTTP 工作流程,最后结合 Linux Socket 手写一个极简 HTTP 服务器,把网络编程真正落地到网页访问。
一、HTTP 协议基础概念
1. 什么是 HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议),是应用层 协议,基于 TCP 实现。
作用:用于 浏览器 <-> 服务器 之间传输超文本数据(HTML、图片、CSS、JS、接口 JSON 等)。
2. HTTP 核心特点
- 基于 TCP 可靠传输 默认端口:80
- 无状态服务器不记录客户端是谁,每次请求都是独立的;靠 Cookie / Session / Token 做身份记录。
- 明文传输数据不加密,所以有了 HTTPS(HTTP+SSL/TLS 加密)。
- 请求 - 响应模型客户端发请求 → 服务器返回响应,一问一答。
- 简单灵活文本格式,易读、易解析。
3. HTTP 工作流程
- 浏览器域名解析 DNS → 拿到服务器 IP
- 浏览器和服务器 TCP 三次握手 建立连接
- 浏览器发送 HTTP 请求报文
- 服务器解析请求,返回 HTTP 响应报文
- 浏览器渲染页面 / 解析数据
- 断开连接(短连接)或保持长连接
二、HTTP 报文整体结构
HTTP 分两种报文:
- HTTP 请求报文:浏览器 → 服务器
- HTTP 响应报文:服务器 → 浏览器
都由三部分组成:
- 起始行(请求行 / 状态行)
- 请求头 / 响应头
- 空行
- 实体体(请求体 / 响应体,可选)
三、HTTP 请求报文详解
1. 请求行格式
bash
请求方法 URL HTTP版本
示例:
bash
GET /index.html HTTP/1.1
2. 常见请求方法
- GET:获取资源,参数拼在 URL 后面,无请求体
- POST:提交数据,有请求体,用于登录、表单提交
- PUT:修改资源
- DELETE:删除资源
- HEAD:只拿响应头,不拿响应体
- OPTIONS:询问服务器支持的请求方法
3. 请求头(Request Headers)
常用字段:
bash
Host: 服务器域名/IP
User-Agent: 浏览器客户端标识
Accept: 能接收的数据类型
Content-Type: 请求体数据格式
Content-Length: 请求体长度
Cookie: 身份凭证
Connection: keep-alive 保持长连接 / close 短连接
4. 请求体
只有 POST/PUT 等方法才有,存放提交的表单数据、JSON 数据。
四、HTTP 响应报文详解
1. 状态行格式
bash
HTTP版本 状态码 描述信息
示例:
bash
HTTP/1.1 200 OK
2. 常用状态码
2xx 成功
- 200 OK:请求成功
3xx 重定向
- 301:永久重定向
- 302:临时重定向
- 304:资源未修改,走缓存
4xx 客户端错误
- 404 Not Found:资源不存在
- 403 Forbidden:禁止访问
- 400 Bad Request:请求报文格式错误
5xx 服务器错误
- 500 服务器内部错误
- 502 网关错误
- 503 服务不可用
3. 响应头
plaintext
bash
Server: 服务器软件
Content-Type: 响应数据类型(text/html、application/json)
Content-Length: 响应体长度
Connection: keep-alive
Set-Cookie: 下发Cookie给浏览器
4. 响应体
真正返回给浏览器的数据:HTML 页面、图片、JSON、文件等。
五、HTTP/1.0 与 HTTP/1.1 区别
- HTTP/1.0
- 默认短连接:一次请求响应完,立刻四次挥手断开 TCP
- HTTP/1.1
- 默认长连接:Connection: keep-alive
- 一个 TCP 连接可以多次 HTTP 请求响应
- 支持断点续传、管道请求
六、Linux 网络编程:手写极简 HTTP 服务器
利用前面 TCP 套接字知识,写一个能被浏览器直接访问的 HTTP 服务器。
功能
- 基于 TCP
- 浏览器访问
127.0.0.1:8080 - 服务器返回一段 HTML 网页
c
运行
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 8080
#define BUF_SIZE 1024
// 构造HTTP响应
char *http_response =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html;charset=utf-8\r\n"
"Content-Length: 80\r\n"
"Connection: close\r\n"
"\r\n"
"<html><body><h1>Hello Linux HTTP Server</h1><p>自制HTTP协议服务器</p></body></html>";
int main()
{
int lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd < 0){
perror("socket");
return 0;
}
// 端口复用
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
struct sockaddr_in serv;
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(PORT);
serv.sin_addr.s_addr = INADDR_ANY;
bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
listen(lfd, 5);
printf("极简HTTP服务器启动成功,端口%d\n", PORT);
printf("浏览器访问:http://127.0.0.1:8080\n");
char buf[BUF_SIZE];
while(1)
{
struct sockaddr_in clnt;
socklen_t len = sizeof(clnt);
int cfd = accept(lfd, (struct sockaddr *)&clnt, &len);
// 读取浏览器发来的HTTP请求报文
read(cfd, buf, BUF_SIZE);
printf("收到HTTP请求:\n%s\n", buf);
// 固定返回HTTP响应
write(cfd, http_response, strlen(http_response));
close(cfd);
memset(buf, 0, BUF_SIZE);
}
close(lfd);
return 0;
}
编译运行
bash
gcc http_server.c -o http_server
./http_server
打开浏览器输入:
bash
http://127.0.0.1:8080
就能看到网页内容,这就是最底层 HTTP 协议的工作过程。
七、HTTP 与 HTTPS 简单区别
- HTTP:明文、端口 80、不安全、容易被抓包篡改
- HTTPS:HTTP + SSL/TLS 加密、端口 443、传输加密、安全
八、学习小结
- HTTP 是应用层协议,底层基于 TCP 可靠传输。
- 分为请求报文、响应报文,都是文本格式,结构固定。
- 掌握常用请求方法、状态码、请求头、响应头是网络编程必备。
- HTTP/1.1 默认长连接,减少频繁三次握手 / 四次挥手开销。
- 可以用原生 Linux Socket 手写极简 HTTP 服务器,理解浏览器和服务器交互本质。
- HTTPS 就是 HTTP 加加密,解决明文不安全问题。