1. 计算机网络基础
1.1 TCP/IP 基础
什么是 TCP/IP?
TCP/IP 是互联网通信的 协议族,它定义了数据如何在网络中传输。TCP 和 IP 是其中最核心的两个协议:
- IP(Internet Protocol):负责将数据包从一台计算机发送到另一台计算机,它只关心“如何到达”,但不保证数据是否丢失或顺序正确。
- TCP(Transmission Control Protocol):建立在 IP 之上,提供可靠的、面向连接的通信。它会确保数据包按顺序到达、没有丢失,如果丢失就重传。
三次握手(建立连接)
当客户端(如浏览器)想和服务器建立 TCP 连接时,会进行 三次握手:
- 客户端 → 服务器:发送一个 SYN(同步)包,表示“我想跟你建立连接”。
- 服务器 → 客户端:回复 SYN-ACK 包,表示“我收到了你的请求,并且我也同意建立连接”。
- 客户端 → 服务器:发送 ACK 包,表示“好的,连接建立成功”。
为什么是三次?
确保双方的收发能力都正常。第一次握手证明客户端能发,第二次证明服务器能收也能发,第三次证明客户端能收。如果只有两次,服务器无法确认客户端是否收到了自己的确认包。
四次挥手(断开连接)
当通信结束时,需要 四次挥手 断开连接:
- 客户端 → 服务器:发送 FIN 包,表示“我要关闭连接了”。
- 服务器 → 客户端:回复 ACK 包,表示“我收到了你的关闭请求”。
- 服务器 → 客户端:发送 FIN 包,表示“我也准备关闭了”。
- 客户端 → 服务器:回复 ACK 包,表示“好的,可以关闭了”。
为什么是四次?
因为 TCP 连接是 全双工 的,双方都可以独立地关闭自己的通道。客户端发送 FIN 表示自己不再发送数据,但服务器可能还有数据要发,所以服务器先回复 ACK 确认,然后等自己的数据发完再发 FIN。所以多了一步。
TCP 与 UDP 的区别
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠传输(确认、重传、顺序) | 不可靠,可能丢包、乱序 |
| 速度 | 较慢,因为要保证可靠性 | 较快,没有额外开销 |
| 应用场景 | HTTP、FTP、邮件等需要可靠传输的场景 | 视频直播、DNS、游戏等允许丢包的场景 |
一句话总结:网络协议就是计算机之间的“通信规则”,TCP 保证数据不丢,UDP 追求速度。
1.2 DNS 解析:域名如何变成 IP
当你在浏览器输入 www.example.com 时,计算机需要知道这个域名对应的 IP 地址才能建立连接。这个过程叫 DNS 解析,大致流程如下:
- 浏览器缓存:先检查浏览器是否缓存了该域名的 IP。
- 操作系统缓存:如果浏览器没有,就检查操作系统的 hosts 文件或 DNS 缓存。
- 本地 DNS 服务器:如果操作系统也没有,就向配置的本地 DNS 服务器(如路由器或 ISP 提供的)发起请求。
- 递归查询:本地 DNS 服务器会代表客户端向根域名服务器、顶级域名服务器(如 .com)、权威域名服务器依次查询,最终获得 IP。
- 返回结果:本地 DNS 服务器将 IP 返回给客户端,并缓存一段时间(TTL)。
简单比喻:DNS 就像电话簿,你只知道对方的名字(域名),通过电话簿查到对方的电话号码(IP)。
1.3 端口
端口 是计算机上用于区分不同网络服务的 逻辑编号,范围 0~65535。当数据包到达计算机时,操作系统根据端口号将数据交给对应的应用程序。
- 为什么后端服务要监听端口?
服务器上可能同时运行 Web 服务(监听 80)、数据库(监听 3306)等,通过端口号区分不同服务。客户端必须指定端口才能与正确的服务通信。
常见端口号:
- 80:HTTP(默认)
- 443:HTTPS
- 3306:MySQL 数据库
- 6379:Redis 缓存
- 8000:常用于开发测试(如 Django 开发服务器)
2. HTTP 协议详解
HTTP(HyperText Transfer Protocol)是浏览器和服务器之间通信的 协议,它定义了请求和响应的格式。
一句话总结:HTTP 就是浏览器和服务器之间的“对话格式”——请求怎么写、响应怎么回、状态码代表什么意思。
2.1 请求方法
HTTP 定义了多种 请求方法,表示对资源要执行的操作:
| 方法 | 语义 | 说明 |
|---|---|---|
| GET | 获取资源 | 只请求数据,不修改资源,幂等(多次请求结果相同) |
| POST | 提交数据(创建资源) | 常用于表单提交、上传文件,非幂等 |
| PUT | 更新资源(全量替换) | 将整个资源替换为请求体内容,幂等 |
| PATCH | 部分更新资源 | 只修改资源的部分字段,幂等 |
| DELETE | 删除资源 | 幂等 |
注意:虽然 GET 也可以携带数据(通过 URL 参数),但通常不建议用 GET 发送敏感信息,因为 URL 会被记录在日志中。
2.2 状态码
服务器响应的状态码表示请求的处理结果,分为五类:
- 1xx:信息性(如 100 Continue)
- 2xx:成功
- 200 OK:请求成功
- 201 Created:资源创建成功(常用于 POST)
- 204 No Content:请求成功,但无返回内容(如 DELETE 成功)
- 3xx:重定向
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 4xx:客户端错误
- 400 Bad Request:请求格式错误
- 401 Unauthorized:未认证(需要登录)
- 403 Forbidden:禁止访问(即使认证了也无权限)
- 404 Not Found:资源不存在
- 5xx:服务器错误
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误
- 503 Service Unavailable:服务不可用(如过载)
2.3 请求和响应结构
HTTP 请求
一个典型的 HTTP 请求包含:
GET /users/123 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0
Accept: application/json
- 请求行:方法 + 路径 + HTTP 版本
- 请求头:键值对,包含额外信息(如 Host、User-Agent、Content-Type)
- 空行:分隔头部和主体
- 请求体:可选,用于 POST、PUT 等携带数据
HTTP 响应
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 123
{"id": 123, "name": "Alice"}
- 状态行:HTTP 版本 + 状态码 + 状态短语
- 响应头:键值对
- 空行
- 响应体:返回的数据
2.4 Content-Type
Content-Type 头部告诉接收方数据的格式,常见的有:
- application/json:JSON 格式数据
- application/x-www-form-urlencoded:表单数据(键值对,如
name=Alice&age=25) - multipart/form-data:用于文件上传(每个部分用 boundary 分隔)
- text/html:HTML 文档
- text/plain:纯文本
2.5 Cookie 和 Session
HTTP 是 无状态 协议,即服务器默认不会记住之前的请求。但 Web 应用需要记住用户登录状态,于是引入了 Cookie 和 Session。
- Cookie:浏览器保存的小段文本,由服务器通过
Set-Cookie头部发送给浏览器,浏览器后续请求会自动带上。通常用来存储 session ID。 - Session:服务器端存储的用户数据,通过 session ID 关联。用户登录后,服务器创建 session,并将 session ID 通过 Cookie 发给客户端。
工作流程:
- 用户登录 → 服务器验证身份,创建 session,生成 session ID。
- 服务器在响应头中设置
Set-Cookie: sessionid=abc123。 - 浏览器保存该 Cookie,后续请求自动在
Cookie头部携带sessionid=abc123。 - 服务器根据 session ID 找到对应的 session 数据,从而识别用户。
2.6 HTTPS
HTTPS = HTTP + SSL/TLS,它在 HTTP 和 TCP 之间加了一层加密层,保证数据传输的 机密性、完整性、身份验证。
基本流程:
- 客户端请求服务器证书(公钥)。
- 服务器返回证书(包含公钥和签名)。
- 客户端验证证书的合法性(是否由可信 CA 签发,域名是否匹配)。
- 客户端生成一个对称加密密钥,用服务器的公钥加密后发送给服务器。
- 双方使用这个对称密钥进行加密通信。
为什么比 HTTP 安全?
- HTTP 传输是明文,容易被窃听、篡改。
- HTTPS 加密后,即使数据被截获也无法解密,且通过证书防止中间人攻击。
2.7 CORS(跨域资源共享)
什么是跨域?
当浏览器向不同源(协议、域名、端口任一不同)的服务器发送请求时,就产生了跨域。浏览器出于安全考虑,限制脚本发起的跨域 HTTP 请求(除非服务器明确允许)。
为什么会有跨域限制?
防止恶意网站通过脚本访问其他网站的数据(如从 A 网站向 B 银行网站发送请求获取用户信息)。这是浏览器的同源策略。
如何解决?
服务器需要在响应头中加入 CORS 相关头部,告诉浏览器允许跨域:
Access-Control-Allow-Origin: *(允许所有域,或指定具体域名)Access-Control-Allow-Methods: GET, POST, PUT(允许的请求方法)Access-Control-Allow-Headers: Content-Type(允许的自定义头部)
对于复杂请求(如 PUT、DELETE 或带自定义头),浏览器会先发送一个 OPTIONS 预检请求,确认服务器允许后才会发送实际请求。
3. RESTful API 设计规范
RESTful 是一种 API 设计风格,它利用 HTTP 协议的特性,使 API 更加清晰、易于理解。
一句话总结:RESTful 就是一套“怎么设计好用的 API”的约定。
3.1 URL 设计
- 使用 名词复数 表示资源集合,例如
/users表示所有用户,/users/123表示特定用户。 - 资源层级用
/表示,例如/users/123/orders表示用户 123 的订单列表。 - 避免在 URL 中使用动词,操作由 HTTP 方法表达。
3.2 HTTP 方法对应 CRUD
| 操作 | HTTP 方法 | URL | 说明 |
|---|---|---|---|
| 创建 | POST | /users | 创建新用户 |
| 读取 | GET | /users | 获取用户列表 |
| 读取 | GET | /users/123 | 获取用户 123 的详细信息 |
| 全量更新 | PUT | /users/123 | 替换用户 123 的全部信息 |
| 部分更新 | PATCH | /users/123 | 更新用户 123 的部分字段 |
| 删除 | DELETE | /users/123 | 删除用户 123 |
3.3 统一响应格式
建议返回统一的 JSON 结构,包含状态码、消息和数据,方便前端统一处理:
{
"code": 200,
"message": "success",
"data": { "id": 123, "name": "Alice" }
}
或者使用 HTTP 状态码表示结果,data 直接放资源(但需要处理错误时格式一致)。
3.4 分页、排序、过滤、搜索
- 分页:使用
page和page_size参数,如GET /users?page=2&page_size=20,响应中返回总条数、当前页数据。 - 排序:
sort参数,如GET /users?sort=name,-created_at(+表示升序,-表示降序)。 - 过滤:用字段名作为参数,如
GET /users?age=25&city=Beijing。 - 搜索:用
q或search参数,如GET /users?q=alice。
3.5 API 版本管理
当 API 发生不兼容更新时,需要版本管理。常见方式:
- URL 路径:
/api/v1/users,/api/v2/users - 请求头:
Accept: application/vnd.myapp.v1+json - 参数:
/users?version=1
最简单且常用的方式是在 URL 中包含版本号。
4. 认证与授权基础
认证(Authentication):验证你是谁(比如登录)。
授权(Authorization):确定你能做什么(比如普通用户不能删除其他用户)。
4.1 Session 与 Token
| 特性 | Session | Token(如 JWT) |
|---|---|---|
| 存储位置 | 服务器存储 session 数据,客户端只存 session ID | 客户端存储 token,服务器不存储(或仅验证) |
| 状态 | 有状态(服务器需要记录 session) | 无状态(服务器通过 token 自身携带的信息验证) |
| 扩展性 | 在分布式环境中需要共享 session(如 Redis) | 天然适合分布式,token 自包含 |
| 缺点 | 占用服务器内存,扩展复杂 | token 一旦签发,难以吊销(除非加黑名单) |
Session 流程:
- 登录成功 → 服务器创建 session,返回 session ID(通过 Cookie)。
- 后续请求携带 Cookie → 服务器根据 session ID 查找 session。
Token 流程:
- 登录成功 → 服务器生成 token(如 JWT)返回给客户端。
- 客户端在后续请求的
Authorization头中携带Bearer <token>。 - 服务器验证 token 签名,解析出用户信息,无需查询 session。
4.2 JWT(JSON Web Token)
JWT 是一种常用的 token 格式,它由三部分组成,用点分隔:
header.payload.signature
- Header:包含类型(JWT)和签名算法(如 HS256)。
- Payload:包含用户自定义的数据(如 user_id、过期时间 exp)。
- Signature:对前两部分进行签名,防止篡改。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
生成和验证:
- 服务器使用密钥(对称算法)或私钥(非对称)对 header 和 payload 进行签名。
- 验证时,服务器用同样的密钥或公钥重新计算签名,比对是否一致,并检查过期时间。
一句话总结:JWT 是一种自包含的 token,服务器不需要存储 session,只需验证签名即可信任其中的数据。
4.3 OAuth 2.0(第三方登录)
OAuth 2.0 是一种授权协议,允许用户授权第三方应用访问自己在某个服务上的资源(比如用 GitHub 账号登录你的网站)。最常见的流程是 授权码模式(以 GitHub 登录为例):
- 用户在你的网站点击“使用 GitHub 登录”,跳转到 GitHub 授权页面。
- 用户同意授权后,GitHub 重定向回你的网站,并携带一个 授权码。
- 你的后端服务器使用授权码向 GitHub 请求 访问令牌(access token)。
- 拿到访问令牌后,可以用它调用 GitHub API 获取用户信息(如用户名、邮箱)。
- 根据获取的信息,在你的系统中创建或登录用户。
注意:OAuth 2.0 的核心是授权,不是认证。但它常被用来实现第三方登录(通过授权获取用户信息来认证)。
4.4 密码安全
- 绝对不要明文存储密码!一旦数据库泄露,用户密码就暴露了。
- 应该存储 密码的哈希值,哈希是单向函数,无法从哈希值还原密码。
- 使用 加盐哈希:对每个用户生成随机盐,与密码拼接后哈希,防止彩虹表攻击。
- 推荐使用 bcrypt 或 argon2 等专门为密码设计的哈希算法,它们自动处理盐和迭代次数,且计算缓慢,可以抵御暴力破解。
示例(Python bcrypt):
import bcrypt
# 哈希密码
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(b"my_password", salt)
# 验证密码
if bcrypt.checkpw(b"my_password", hashed):
print("密码正确")
一句话总结:认证 = “你是谁”,授权 = “你能干什么”。千万不要自己“发明”加密算法,用成熟的库(bcrypt、passlib)就对了。
5. 练习
5.1 使用 curl 或 Postman 观察 HTTP 细节
curl 是命令行工具,可以发送各种 HTTP 请求。试着执行以下命令,观察输出:
# 发送 GET 请求,显示响应头和响应体
curl -v https://api.github.com/users/octocat
# 发送 POST 请求,携带 JSON 数据
curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice"}' http://httpbin.org/post
Postman 是图形化工具,可以更方便地构建请求、查看头部和响应。尝试创建一个请求,观察请求头、响应头、状态码。
5.2 用 Python 的 http.server 写一个最简单的 HTTP 服务器
Python 内置了 http.server 模块,可以快速启动一个静态文件服务器,也可以自定义处理逻辑。
例子 1:启动静态服务器
python -m http.server 8000
访问 http://localhost:8000,可以看到当前目录的文件列表。
例子 2:自定义请求处理
from http.server import HTTPServer, BaseHTTPRequestHandler
class SimpleHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
self.wfile.write(b'Hello, World!')
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
print("Received POST data:", post_data)
self.send_response(200)
self.end_headers()
self.wfile.write(b'POST received')
server = HTTPServer(('localhost', 8000), SimpleHandler)
print("Server running on http://localhost:8000")
server.serve_forever()
运行后,用 curl 测试:
curl -v http://localhost:8000
curl -X POST -d "hello" http://localhost:8000
观察请求和响应的完整过程。
5.3 画一张 HTTP 请求的完整流程图
结合本章知识,画一张从用户在浏览器输入 URL 到看到页面的流程图,包含以下环节:
- DNS 解析
- TCP 三次握手
- 发送 HTTP 请求
- 服务器处理请求
- 返回 HTTP 响应
- TCP 四次挥手
- 浏览器渲染页面
你可以用纸笔画,也可以用流程图工具。这有助于将零散的知识串联起来。
6. 总结
- 计算机网络 让你明白数据是如何在互联网上传输的,三次握手和四次挥手是面试常考的重点。
- HTTP 协议 是浏览器与服务器对话的语言,请求方法、状态码、头部、Cookie/Session、HTTPS、CORS 都是日常开发中频繁打交道的知识点。
- RESTful 设计规范 提供了一套优雅的 API 设计思路,让前后端协作更顺畅。
- 认证与授权 保障了 Web 应用的安全性,Session、JWT、OAuth 2.0 和密码哈希是构建用户系统的基石。

京公网安备 11010502036488号