计算机网络基础
这是人工智能训练师基础系列的第六章。计算机网络是知识体系里的重点章节,核心概念必须能讲明白——OSI 模型、TCP/UDP、HTTP/HTTPS、DNS、IP 地址与子网划分这几块都要落到细节。这一章的核心问题就一个:”数据怎么传”——从你按下回车到网页打开,中间到底发生了什么。下面跟着串讲走一遍,遗忘的内容就能捡回来。
计算机网络:数据怎么传
网络是重点章节,概念多但相对好理解。
OSI与TCP/IP模型
OSI 七层模型从下到上:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。用”寄快递分层”来类比很好记:物理层管”用什么车走什么路”(比特流传输);数据链路层管”两个相邻站点之间怎么可靠传一帧”(MAC 地址寻址,以太网、Wi-Fi 在这层);网络层管”包裹怎么从源头路由到目的地”(IP 协议在这层);传输层管”端到端的一次完整通信”(TCP/UDP,端口号);会话层管”建立、管理、终止会话”;表示层管”数据怎么编码、加密、压缩”;应用层管”给用户应用提供网络服务”(HTTP、FTP、DNS、SMTP)。
实际中会话层和表示层基本并入应用层,所以 TCP/IP 四层模型更贴近现实:网络接口层、网际层(IP)、传输层(TCP/UDP)、应用层。也有教材把 TCP/IP 写成五层模型,是一回事。
记忆口诀(从下到上):物、数、网、传、会、表、应。每层对应的设备:物理层有中继器、集线器(hub);数据链路层有交换机(switch)、网桥;网络层有路由器(router);传输层以上是网关、防火墙。
每层对应的常见协议也得知道一两个,否则题目里给你一个协议名问你属于哪层你答不上来。物理层主要是电气规范,比如以太网的物理层规范 IEEE 802.3;数据链路层有以太网协议(Ethernet)、PPP(点对点协议);网络层有 IP(IPv4/IPv6)、ICMP(就是 ping 用的那个)、ARP(把 IP 解析成 MAC 地址);传输层有 TCP 和 UDP;会话层和表示层在 TCP/IP 体系里基本被并入应用层,可以记 RPC、SSL/TLS、JPEG 这类做编码加密的活儿;应用层协议最多,HTTP、HTTPS、FTP、SMTP、DNS、SSH、DHCP 都在这一层。看到一个协议名你能马上反应它在第几层,这是基本盘。
数据封装过程也要会:发送方从上到下,每经过一层加一个首部(应用数据→加 TCP 头成段 segment→加 IP 头成包 packet→加帧头帧尾成帧 frame→变成比特流);接收方反过来一层层剥。这个”封装—解封装”是重点知识。
数据封装过程实例
光说”加头加头加头”还是抽象,咱们把一次具体的网页请求跟着走一遍。假设你在浏览器里输入了一个网址,要发一段”Hello”给服务器,数据从你的电脑一层层被”穿衣服”再发出去的过程是这样的:
- 第一步(应用层):浏览器把”Hello”加上一个 HTTP 请求头,里面写着”GET / HTTP/1.1”、Host、User-Agent 这些字段。这时数据叫”消息”(message)。
- 第二步(传输层):TCP 给它加上 TCP 头,头里包含源端口号(比如你的浏览器临时端口 54321)、目的端口号(HTTP 默认 80)、序号 seq、确认号 ack、控制标志 SYN/ACK/FIN 等。这时数据叫”段”(segment)。
- 第三步(网络层):IP 再加上 IP 头,头里包含源 IP(你的本机 IP,比如 192.168.1.10)、目的 IP(服务器的 IP,比如 93.184.216.34)、TTL(生存时间,防止数据包在网络里无限循环)等。这时数据叫”包”(packet)。
- 第四步(数据链路层):再加上帧头(包含源 MAC 地址和目的 MAC 地址,MAC 是网卡的物理地址)和帧尾(FCS 帧校验序列,用于接收方检查数据有没有传错)。这时数据叫”帧”(frame)。
- 第五步(物理层):帧被转成比特流,通过网线或无线电波变成电信号或光信号一比特一比特发出去。
到了服务器那边,接收方反过来一层层剥:物理层把比特流组装成帧→数据链路层校验 FCS、剥掉帧头帧尾→网络层读 IP 头看目的 IP 是不是自己→传输层读 TCP 头交给对应端口的进程→应用层读 HTTP 头把”Hello”交给 web 服务器处理。一层对应一层,谁加的谁剥,谁也不越俎代庖。这个”层层加头、层层剥头”的过程就是封装和解封装,理解了它你就理解了分层模型的本质——每层只管自己那一层的活儿,不关心上下层在干什么。
TCP与UDP
TCP 像打电话要确认:建立连接(三次握手)、传输时确认收到、丢了重传、按顺序到达,可靠但慢,开销大。UDP 像寄明信片:发出去就不管了,不建连接、不确认、不重传、不保证顺序,不可靠但快、开销小。
TCP三次握手的具体序号示例
光说”SYN、SYN+ACK、ACK”还是抽象,咱们带具体数字走一遍。假设客户端初始序号 seq=x,咱们设 x=1000;服务器初始序号 seq=y,咱们设 y=5000。
- 第一次握手:客户端发 SYN 报文,seq=1000。这一步客户端告诉服务器”我想跟你建立连接,我的初始序号是 1000”。这时客户端进入 SYN_SENT 状态。
- 第二次握手:服务器收到 SYN 后回 SYN+ACK,seq=5000,ack=1001。服务器既确认收到了客户端的 SYN(ack=1001 表示”我收到你 1000 了,你下一个发 1001”),又告诉客户端自己的初始序号是 5000。这时服务器进入 SYN_RCVD 状态。
- 第三次握手:客户端收到 SYN+ACK 后回 ACK,seq=1001,ack=5001。客户端确认收到服务器的 SYN(ack=5001 表示”我收到你 5000 了,你下一个发 5001”)。这时双方都进入 ESTABLISHED 状态,连接建立。
为什么是三次不是两次?这里得从”双向确认”的角度想。建立 TCP 连接是为了双方都能发能收,所以两个方向各要确认一次”我能发”和”你能收”。第一次握手,服务器确认了客户端能发;第二次握手,客户端确认了服务器能收、也能发;第三次握手,服务器确认了客户端能收。两次握手只能让客户端确认服务器的发送和接收能力,但服务器还没确认客户端的接收能力——万一是网络里滞留的一个旧连接请求呢?如果只两次握手,服务器一收到 SYN 就建立连接、分配资源,结果这个请求是个迟到几小时的旧包,那服务器就白建一个连接白占资源了。三次握手多一步确认,就能让旧包没法错误地建立连接,因为客户端根本没发过这个 SYN,不会回第三次的 ACK。
TCP四次挥手的具体序号示例
接着上面的序号继续。假设现在数据传完了,客户端要主动断开连接。当前客户端 seq=1001,ack=5001。
- 第一次挥手:客户端发 FIN,seq=1001,ack=5001。客户端进入 FIN_WAIT_1 状态,意思是”我没数据要发了,可以关了”。
- 第二次挥手:服务器回 ACK,ack=1002。服务器进入 CLOSE_WAIT 状态。注意这一步服务器只是确认收到了客户端的 FIN,但服务器自己可能还有没发完的数据,得先把剩下的发完。客户端收到这个 ACK 后进入 FIN_WAIT_2 状态。
- 第三次挥手:服务器把剩下的数据发完后,也发 FIN,seq=5001。服务器进入 LAST_ACK 状态,意思是”我也没数据了,可以关了”。
- 第四次挥手:客户端回 ACK,ack=5002。客户端进入 TIME_WAIT 状态,等待 2 个 MSL(最大报文段寿命,Max Segment Lifetime)后才真正关闭。服务器收到这个 ACK 后直接进入 CLOSED 状态。
为什么是四次不是三次?因为 TCP 是全双工的——双方都能同时发数据,所以两个方向各要单独关闭。建立连接时,服务器的 SYN 和 ACK 可以合并成一个 SYN+ACK 一次发出去;但断开时,服务器收到客户端的 FIN 后可能还有数据没发完,不能立刻发自己的 FIN,所以 ACK 和 FIN 必须分两次发,于是就成了四次。
TIME_WAIT 状态要专门讲一下,这是重点知识。客户端发完最后一个 ACK 后不直接关闭,而是进入 TIME_WAIT,等 2 个 MSL 才真正 CLOSED。为什么?两个理由:一是客户端发的最后一个 ACK 可能丢了,服务器会重传 FIN,客户端得留着状态准备重传 ACK;二是让本次连接的旧报文都在网络里”自然死亡”,2 个 MSL 后旧包都会因为 TTL 到期被丢弃,不会污染下一次新建的连接。所以 TIME_WAIT 是为了可靠性主动做的等待,不是 bug。常见面试题问”为什么服务器端高并发时会有大量 TIME_WAIT?”——其实 TIME_WAIT 通常出现在主动关闭方,服务器如果总是被客户端主动断开,自己这边是 CLOSE_WAIT,反过来如果服务器主动断开才会出现 TIME_WAIT,这个方向别记反。
TCP可靠性机制
TCP 可靠性靠这些机制保证:序号和确认号、重传、流量控制(滑动窗口)、拥塞控制(慢启动、拥塞避免、快重传、快恢复)。
滑动窗口做的是流量控制——发送方不能一股脑把数据全发出去把接收方淹没,得根据接收方的处理能力来。具体过程是这样的:接收方在 ACK 报文里带一个”窗口大小”字段(rwnd,接收窗口),告诉发送方”我还能接收多少字节”。发送方就维护一个发送窗口,窗口大小等于 rwnd,窗口内的数据可以连续发出去不等确认,窗口外的数据必须等收到 ACK 让窗口向前滑动后才能发。
举个例子,假设接收方通告窗口 rwnd=4000 字节,发送方有 6000 字节要发。窗口内的前 4000 字节先连续发出去,剩下 2000 字节得等。接收方收到前 1000 字节、处理完后回 ACK 时把窗口通告更新成 5000(因为它处理掉 1000 字节腾出了空间),发送方窗口向前滑动 1000 字节,又能多发 1000 字节了。如果接收方处理不过来、缓冲区快满了,就会把窗口通告改小,比如改成 500,发送方就发慢点;如果接收方完全处理不过来,会通告窗口=0(零窗口),发送方就停发,定期发零窗口探测包看接收方啥时候缓过来。这就是滑动窗口流量控制——接收方通过窗口大小动态指挥发送方”快一点、慢一点、停下来”。
拥塞控制做的是另一件事——防止网络本身被压垮。滑动窗口管的是”接收方能不能扛得住”,拥塞控制管的是”网络中间的链路和路由器能不能扛得住”。发送方维护一个拥塞窗口 cwnd,实际发送窗口 = min(rwnd, cwnd)。拥塞控制有四个经典阶段:
- 慢启动:连接刚建立时 cwnd=1(一个 MSS,最大报文段大小),每收到一个 ACK 就 cwnd+1,结果就是每个 RTT(往返时间)窗口翻倍,呈指数增长,1→2→4→8→16……这一阶段叫慢启动不是因为慢,而是初始值小、增长快。一直涨到 ssthresh(慢启动阈值)才换档。
- 拥塞避免:cwnd 到了 ssthresh 之后改成线性增长,每个 RTT 只加 1,1→2→3→4……增长慢下来稳着跑,避免一下子冲爆网络。
- 快重传:如果发送方连续收到 3 个重复 ACK,说明这个包丢了,立刻重传那个丢失的包,不用等超时计时器到期。
- 快恢复:快重传后不回到慢启动阶段,而是把 ssthresh 设为当前 cwnd 的一半,cwnd 也设为这个新 ssthresh,然后进入拥塞避免线性增长,不从头开始。
如果是真超时(不是 3 个重复 ACK 踩出来的),那就比较严重了,ssthresh 设为当前 cwnd 的一半,cwnd 直接回到 1,从头开始慢启动。所以”3 个重复 ACK”和”真超时”是两种不同程度的拥塞信号,前者轻、后者重,恢复策略也不一样,这个对比要分清。
TCP vs UDP的应用场景对比
光说”TCP 可靠、UDP 快”还不够具体,得知道哪些应用用哪个、为什么。下面挑几个典型场景,照着”应用对协议的诉求”来配对,配得对就答得对。
TCP 适合”不能丢、必须按序到达”的场景。HTTP 和 HTTPS(网页浏览)——少一个字节网页就显示不正常,必须可靠;FTP(文件传输)——文件传一半错个位就废了;SMTP/POP3/IMAP(邮件)——邮件少一段内容不行;SSH(远程登录)——你打的每个字符都得准确到达,错一个就命令变了。这些应用里,可靠性比实时性重要,所以选 TCP。
UDP 适合”要快、能容忍丢包、要支持一对多”的场景。DNS 查询——就一个小小的请求和响应,建 TCP 连接三次握手太奢侈,UDP 一来一回最干脆;视频直播和语音通话——丢几个包最多花屏或卡顿一下,但延迟一大就完全没法用;网络游戏——同步位置信息要实时,旧的数据到了也没意义宁可丢;DHCP(动态主机分配 IP)——客户端连 IP 都没有,根本没法建 TCP 连接,只能用 UDP。共同点是对实时性要求高、对单包可靠性要求低,所以选 UDP。
常见的对比点还有:DNS 既可以走 UDP 也可以走 TCP,区域传送(zone transfer,整个区域数据同步)用 TCP 因为数据大、要可靠,但普通查询用 UDP;HTTP/3 之前 HTTP 都基于 TCP,HTTP/3 改用了基于 UDP 的 QUIC 协议【需网络查询确认:HTTP/3 标准化时间和 QUIC 详细 RFC】,这是为了减少握手延迟。看到”DNS 一定用 UDP””HTTP 一定用 TCP”这种绝对化表述要警惕。
HTTP与HTTPS
HTTP 是超文本传输协议,基于 TCP,默认端口 80。它是无状态的(每次请求相互独立,所以才有 Cookie/Session 来维持状态),请求-响应模式。
HTTP报文结构
HTTP 报文的结构像一封信,分四部分:请求行或状态行、头部、空行、主体。
请求行是请求报文的第一行,包含三个内容用空格隔开:方法、路径、版本。比如”GET / HTTP/1.1”,意思是”用 GET 方法访问 / 路径,用 HTTP/1.1 版本”。响应报文的第一行叫状态行,格式类似但内容不同,是”版本 状态码 状态消息”,比如”HTTP/1.1 200 OK”。
接下来是头部,是一系列键值对,每行一个,用来传递附加信息。常见的头部字段你得认识几个:Host 指定服务器域名,这是 HTTP/1.1 强制要求的;Content-Type 告诉对方正文是什么格式,比如 application/json 表示是 JSON 数据;Content-Length 表示正文的字节长度;Cookie 用来携带身份凭证,浏览器自动带上之前服务器设置的 Cookie;User-Agent 标识客户端类型,比如 Chrome/91.0,服务器常拿它做统计或适配。这些字段在调试网络请求时会反复出现,认识它们你就能看懂抓包里的请求长什么样。
头部结束后是一个空行,看起来不起眼,但它有明确的作用——分隔头部和正文。HTTP 解析器看到空行就知道”头部到此为止,后面如果有内容就是主体”。
最后一部分是主体 Body,传输实际的数据。GET 请求一般没有主体(参数拼在 URL 里),POST 请求的主体里放表单数据或 JSON。响应报文的主体里就是服务器返回的 HTML、图片、JSON 等内容。也就是说,头部管”元信息”(这是谁、什么格式、多长),主体管”实际货物”(数据本身)。
HTTP方法的幂等性
HTTP 方法要记:GET(获取资源,幂等、无副作用)、POST(提交数据、创建资源,非幂等)、PUT(更新/替换资源,幂等)、DELETE(删除资源,幂等)。幂等性是指多次执行结果相同,这个概念要重点掌握。
为什么 GET 幂等而 POST 不幂等,光记结论容易忘,咱们看具体例子就明白了。幂等的意思是”同一个请求执行一次和执行多次,对资源状态的影响是一样的”。
GET 的例子:你访问 http://example.com/users/123,第一次拿到用户 123 的资料,再调十次还是拿到同样的资料,服务器上的数据一点没变——这就是幂等,GET 只是读,不改数据。所以浏览器可以放心地缓存 GET 请求、可以刷新重发、可以从历史记录里重新打开,都不会改变服务器状态。
POST 的例子:你向 http://example.com/users 提交一个表单创建新用户,第一次调用创建了一个 ID=1 的用户,再调一次又创建了一个 ID=2 的用户,调十次就建十个用户——服务器状态每次都变了,所以 POST 不幂等。这就是为什么浏览器在 POST 表单后弹”确认重新提交表单”——防止你手滑点了又点创建了一堆重复数据。
PUT 的例子:你向 http://example.com/users/123 PUT 一份数据”名字=张三”,第一次调用把用户 123 的名字改成张三,再调一次还是张三——服务器状态最终都一样,所以 PUT 幂等。PUT 是”幂等的更新”,因为它把整个资源替换成指定状态,不管调多少次结果都是那个状态。
DELETE 的例子:你 DELETE http://example.com/users/123,第一次调用删掉了用户 123,再调一次用户 123 已经不存在了,但服务器状态没变(还是”用户 123 不存在”),所以 DELETE 也算幂等。
一句话总结:GET、PUT、DELETE 幂等,POST 不幂等。常见问题会问”哪些 HTTP 方法是幂等的”,记住这三个就行。
HTTP状态码详解
HTTP 状态码分五类,记住第一位代表什么:1xx 信息、2xx 成功(200 OK、201 Created)、3xx 重定向(301 永久重定向、302 临时重定向、304 Not Modified 缓存)、4xx 客户端错误(400 请求语法错、401 未认证、403 禁止访问、404 找不到)、5xx 服务器错误(500 内部错误、502 网关错误、503 服务不可用、504 网关超时)。
401 和 403 的区别必须分清,这是重点知识。
401 Unauthorized(未认证)意思是”你是谁我还不知道”。具体场景:你访问一个需要登录的页面,但还没登录,服务器回 401,浏览器看到 401 通常会弹出登录框让你输入账号密码。比如你访问 http://example.com/profile,服务器回 401,意思是”先告诉我你是谁”,你登录后再访问,这次请求带了认证信息(Cookie 或 Token),服务器就放行了。所以 401 的本质是”身份没验证”,需要你证明你是谁。
403 Forbidden(禁止访问)意思是”我知道你是谁,但你没权限”。具体场景:你登录了一个普通用户账号,想访问 http://example.com/admin 后台管理页面,服务器知道你是张三(认证通过了),但张三不是管理员,于是回 403。这时你再怎么登录都没用,因为身份对了但权限不够,得管理员把你升级成管理员角色才能访问。
所以 401 是”没登录或登录信息无效”,403 是”登录了但权限不够”。看到”403 是没认证”这种说法是错的,403 是认证过了但被禁止。再补一个常见点 404,它是 Not Found,意思是”服务器上根本没有这个资源”,跟权限无关,是资源本身不存在,比如你访问了一个写错的 URL。这三个码——401、403、404——是 4xx 客户端错误里最常见的,一定分清。
3xx 重定向里 301 和 302 也常见:301 是永久重定向,搜索引擎会更新索引到新地址,适合域名永久搬迁;302 是临时重定向,搜索引擎保留原地址索引,适合临时跳转。304 Not Modified 是配合缓存用的,客户端问了”这个资源自上次以来变过吗”,没变服务器就回 304 让客户端继续用本地缓存,省了重新下载。这个 304 下面讲缓存时还会详细说。
5xx 服务器错误里 500、502、503、504 的区别也容易混:500 是服务器内部代码出错了;502 是网关错误,反向代理服务器从上游服务器拿到的是错误响应;503 是服务暂时不可用,通常是过载或维护;504 是网关超时,反向代理服务器等上游响应等超时了。
HTTP缓存机制
HTTP 缓存能让网页飞起来,第二次访问一个网站之所以快,就是因为缓存省去了重复下载。浏览器缓存分两类:强缓存和协商缓存,理解了它俩的分工你就理解了整个缓存机制。
强缓存的意思是浏览器根本不向服务器发请求,直接读本地缓存。它靠两个字段控制:一个是 Expires,写一个绝对过期时间,比如”2026 年 12 月 31 日 23:59:59 之前都算有效”,这是 HTTP/1.0 的字段,依赖客户端本机时间,万一本机时间不准就会判断错;另一个是 Cache-Control: max-age=3600,写一个相对过期时间,意思是”从服务器返回算起 3600 秒内有效”,这是 HTTP/1.1 的字段,更精准,所以现在以 Cache-Control 为准。强缓存命中时浏览器显示 200 from cache,根本不打扰服务器,是最快的一种。
协商缓存的意思是强缓存过期了,浏览器去问一下服务器”这个资源自上次以来变过吗”,没变就用旧的。它靠两对字段:第一对是 Last-Modified 和 If-Modified-Since,服务器第一次返回资源时带上 Last-Modified 表示最后修改时间,浏览器下次请求时带上 If-Modified-Since 把这个时间还回去,服务器比较后没变就回 304;第二对是 ETag 和 If-None-Match,服务器第一次返回资源时带上 ETag(资源的唯一标识,类似哈希值),浏览器下次请求时带上 If-None-Match 把这个标识还回去,服务器比较后没变就回 304。ETag 比 Last-Modified 更精确,因为有些文件修改了内容没变(比如重新保存但内容相同),Last-Modified 会误判为已修改,而 ETag 基于内容计算就能识别出来。
完整的缓存流程是这样的:浏览器请求一个资源时,先检查强缓存,如果还在有效期内(没过期),直接用本地缓存,状态码显示 200 from cache,根本不打扰服务器;如果强缓存过期了,浏览器就带上协商缓存标识(If-Modified-Since 或 If-None-Match)去问服务器,服务器判断资源没改过就回 304,浏览器继续用本地缓存;如果改过了,服务器就回 200 并返回新资源,浏览器拿到新资源更新缓存。所以 304 就是协商缓存命中的标志,前面状态码里提到的 304 现在你就明白它的来历了。
HTTPS握手详细过程
HTTPS = HTTP + SSL/TLS 加密,默认端口 443。它解决的是 HTTP 明文传输不安全的问题,提供加密(防窃听)、身份认证(防冒充,靠证书)、完整性校验(防篡改)。
HTTPS 握手的核心思想是”用非对称加密安全交换一个对称密钥,之后用对称密钥加密实际数据”。为什么要这样混着用?因为非对称加密慢、对称加密快——非对称加密适合加密小数据(比如密钥本身),对称加密适合加密大数据(比如网页内容)。所以协议设计成:先用慢的非对称加密把对称密钥安全传过去,之后所有的通信都切换到快的对称加密。
具体步骤走一遍:
- 第一步:客户端发 ClientHello,告诉服务器自己支持的 SSL/TLS 版本、支持的加密套件列表(比如 RSA+AES、ECDHE+AES 等)、一个客户端生成的随机数(叫 client_random)。
- 第二步:服务器发 ServerHello,选定一个 SSL/TLS 版本、选定一个加密套件、返回一个服务器生成的随机数(叫 server_random),并把服务器的数字证书发给客户端。证书里包含服务器的公钥,由 CA(证书颁发机构)用私钥签名。
- 第三步:客户端验证证书合法性。验证内容包括:证书是不是受信任的 CA 签发的(用操作系统/浏览器内置的 CA 公钥验签)、证书是否在有效期内、证书里的域名和当前访问的域名是否一致、证书是否被吊销(查 CRL 或 OCSP)。任何一项不过就报警。
- 第四步:客户端生成第三个随机数,叫 pre_master_secret(预主密钥),用服务器证书里的公钥加密后发回服务器。这一步是关键——pre_master_secret 用非对称加密传过去,只有持有私钥的服务器能解开,中间人就算截获也解不开。
- 第五步:服务器用自己的私钥解密得到 pre_master_secret。现在双方手里都有三个数:client_random、server_random、pre_master_secret。双方用同样的算法基于这三个数算出相同的对称会话密钥(master_secret,再派生出加密密钥和 MAC 密钥)。
- 第六步:客户端发 Change Cipher Spec(告诉服务器”之后用对称加密了”)和 Finished(用协商好的密钥加密的第一条消息,让对方验证密钥协商成功)。
- 第七步:服务器也回 Change Cipher Spec 和 Finished。
- 第八步:握手完成。之后客户端和服务器之间所有的 HTTP 通信都用对称密钥加密。
你看,整个过程的核心就是”用非对称加密把 pre_master_secret 安全送到服务器,然后双方用三个随机数算出对称密钥”。为什么需要三个随机数?因为单个随机数可能被预测或重放,三个随机数组合后密钥的不可预测性大幅增强,安全性更高。
关于 CA 证书还要知道一点:CA 是受信任的第三方,它用自己的私钥给服务器的公钥签名,客户端用 CA 的公钥(系统内置)验签。如果验签通过,说明这个公钥确实是这个服务器自己的、没被中间人掉包。这就是 HTTPS 防止中间人攻击的核心机制——中间人就算能截获通信,也伪造不出 CA 的签名。
注意 SSL/TLS 的版本演进也要大概知道:SSL 2.0、3.0 早已不安全被废弃,TLS 1.0、1.1 也基本停用,目前主流是 TLS 1.2 和 TLS 1.3【需网络查询确认:TLS 1.3 RFC 8446 发布时间】。TLS 1.3 大幅简化了握手过程,把往返次数减少到 1-RTT,甚至支持 0-RTT 恢复,进一步降低延迟。
HTTP协议的演进
HTTP 协议本身也在不断演进,了解版本差异能帮你理解为什么现代网页这么快。
HTTP/1.0 时代,每次请求都要新建一个 TCP 连接,请求完就断开,开销很大。HTTP/1.1 引入了持久连接(Keep-Alive),一个 TCP 连接可以连续发多个请求,省去了反复握手挥手的开销;还引入了管道化,允许浏览器在一个连接上连续发多个请求不等响应。但管道化有个问题叫”队头阻塞”——服务器必须按请求顺序返回响应,前面一个慢了后面的都得等着,所以实际中浏览器很少真的用管道化,而是开多个 TCP 连接并行请求。
HTTP/2 解决了队头阻塞问题。它把数据分成一个个帧(frame),每个帧打上流 ID(stream id),属于不同请求的帧可以在同一个 TCP 连接上交叉发送,这就是”多路复用”——一个 TCP 连接上同时跑多个请求和响应,互不阻塞。它还支持头部压缩(用 HPACK 算法减少重复头部的传输,因为 HTTP 头部里很多字段每次请求都重复)和服务器推送(服务器主动把资源推给客户端,比如 HTML 里引用的 CSS,不用等浏览器请求)。HTTP/2 让一个连接扛住大量并发请求成为可能,是现代网页性能提升的关键。
HTTP/3 更激进,干脆不用 TCP 了,改用基于 UDP 的 QUIC 协议【需网络查询确认:HTTP/3 标准化时间和 QUIC 详细 RFC】。为什么?因为 TCP 是内核实现的,握手要 1 个 RTT,TLS 握手又要 1 到 2 个 RTT,加起来延迟不小;而且 TCP 有队头阻塞——一个包丢了,整个连接上后续的包都得等它重传。QUIC 把传输层和加密层合并到一起,握手只要 1 个 RTT 甚至 0 RTT(恢复连接时),而且丢包只阻塞当前流不影响其他流,还支持”连接迁移”——你从 Wi-Fi 切到 4G,连接不会断,因为 QUIC 用连接 ID 而不是 IP 加端口来标识连接。HTTP/3 是 Google 主推的,YouTube 等大站已经在用。
DNS:域名系统的电话本
人记不住 IP 地址(比如 142.250.185.46),但容易记住域名(比如 www.baidu.com)。DNS(域名系统)就是用来把域名翻译成 IP 地址的,相当于互联网的电话本。前面讲过 DNS 是应用层协议、查询通常走 UDP,现在咱们把一次完整的解析过程走一遍。
域名解析的过程是层层递进的询问。假设你在浏览器输入 www.example.com,浏览器要拿到这个域名对应的 IP 才能发请求,它会按这个顺序找。
第一步,浏览器先查自己的 DNS 缓存。浏览器会缓存最近访问过的域名对应的 IP,Chrome 里可以通过 chrome://net-internals/#dns 查看。如果缓存里有且没过期,直接用,查询到此结束。
第二步,浏览器缓存没有,就去问操作系统。操作系统也有自己的 DNS 缓存和 hosts 文件,Windows 用 ipconfig /displaydns 查看,Linux 用 systemd-resolve –statistics 查看。hosts 文件是一个本地的静态映射表,你可以手动写”127.0.0.1 localhost”这样的记录,系统会优先信 hosts 文件,所以开发时常用它来把某个域名指向本地做测试。
第三步,操作系统也没有,就向配置的本地 DNS 服务器发起查询。本地 DNS 服务器通常是你 ISP(运营商)提供的,比如电信的 114.114.114.114 或者 Google 的 8.8.8.8。你在路由器的 DHCP 配置里看到的那个 DNS 地址就是它。
第四步是本地 DNS 服务器去外面的世界找答案,这里有两种查询模式要分清:递归查询和迭代查询。递归查询是”你替我去问到底”——本地 DNS 服务器替客户端去问其他服务器,一路问到拿到最终结果再返回给客户端,就像你问朋友一个问题,他不会,但他去请教别人,最后把答案告诉你。迭代查询是”你告诉我下一步该问谁”——本地 DNS 服务器告诉客户端下一级 DNS 服务器的地址,让客户端自己去问,就像朋友告诉你”这个问题你得问张三,张三的地址是……”。实际中,客户端到本地 DNS 服务器这一段是递归查询(你把活儿全权委托给本地 DNS 服务器),本地 DNS 服务器到外面那一段是迭代查询(它一级一级往下问)。
第五步,本地 DNS 服务器开始迭代查询的链路:先问根 DNS 服务器(全球共 13 组根 DNS,管理顶级域),根 DNS 说”我不知道 www.example.com 的 IP,但我知道负责 .com 的顶级域 DNS 在哪,你去问它”;本地 DNS 服务器再去问顶级域 DNS(负责 .com),顶级域 DNS 说”我不知道 www.example.com 的 IP,但我知道 example.com 这个域的权威 DNS 在哪,你去问它”;本地 DNS 服务器最后去问权威 DNS(example.com 自己的 DNS 服务器),权威 DNS 才是真正知道 www.example.com 对应哪个 IP 的,它返回 IP,本地 DNS 服务器拿到后缓存一份,再返回给客户端。客户端拿到 IP 后也能缓存一份,下次直接用。
你看,整个解析过程就是”层层下问”:从浏览器缓存问到操作系统缓存,再到本地 DNS 服务器,再到根、顶级域、权威 DNS,一级一级往下钻,直到拿到最终的 IP。每一级都可能缓存结果,所以第二次访问同一个域名通常很快。
DNS 还能做负载均衡。大型网站(比如百度)通常把同一个域名对应多个 IP 地址,DNS 服务器在解析时用轮询或者其他策略返回不同的 IP,把流量分发到多台服务器上,避免某一台过载。这就是 DNS 负载均衡——简单粗暴,但在地理分布的流量调度上很有效,比如把北京用户的请求解析到北京机房的 IP,把上海用户的请求解析到上海机房的 IP,靠的就是 DNS 的智能调度。
IP地址与子网划分
IP地址分类与快速判断
IPv4 按网络号位数分类。A 类:第一位 0,范围 1.0.0.0 到 126.255.255.255,默认掩码 /8,127 是环回地址。B 类:前两位 10,范围 128.0.0.0 到 191.255.255.255,默认掩码 /16。C 类:前三位 110,范围 192.0.0.0 到 223.255.255.255,默认掩码 /24。D 类组播(224 到 239),E 类保留(240 到 255)。
如何快速判断一个 IP 属于哪一类?不用记二进制前缀,记 IP 第一段的十进制范围就够了。看 IP 地址第一个点之前的那个数字:
- 1 到 126:A 类。比如 10.0.0.1 是 A 类(其实它是 A 类私有地址)。
- 127:环回地址,不算 A/B/C 任何一类,专门给本机测试用,ping 127.0.0.1 就是 ping 自己。
- 128 到 191:B 类。比如 172.16.0.1 是 B 类(其实它是 B 类私有地址)。
- 192 到 223:C 类。比如 192.168.1.1 是 C 类(其实它是 C 类私有地址)。
- 224 到 239:D 类组播,单播通信不用。
- 240 到 255:E 类保留。
判断口诀就是”看第一段数字落在哪个区间”。比如题目给你一个 200.1.2.3,你看 200 落在 192-223,立刻判断是 C 类,默认掩码 /24。给你 130.5.6.7,130 落在 128-191,是 B 类,默认掩码 /16。这个判断几乎是常识题,但要快、要准,别犹豫。
子网划分完整计算示例
子网划分是计算重点。掩码把 IP 分成”网络位 + 主机位”,借主机位做子网位就能把一个大网切成多个小网。计算套路:给定 IP 和掩码位数 n,网络地址 = IP 与子网掩码按位与;广播地址 = 网络地址的主机位全置 1;可用主机范围 = 网络地址 +1 到 广播地址 -1;可用主机数 = 2 的(32-n)次方减 2(去掉网络号和广播)。CIDR(无类别域间路由)就是用 /n 表示掩码位数,不再死守 A/B/C 分类。NAT(网络地址转换)让内网多台机器共用一个公网 IP 出网。
光记公式不够,咱们拿一道完整题算一遍,你照着这个步骤走,任何子网题都能解。
题目:给定 IP 192.168.1.100/26,求网络地址、广播地址、可用主机范围、可用主机数。
第一步,理解 /26 的含义。26 表示 IP 的前 26 位是网络位,剩下 32-26=6 位是主机位。子网掩码是 26 个连续的 1,写成十进制是 255.255.255.192——前三个 8 位全 1(255),最后 8 位是 11000000(即 192)。
第二步,把 IP 写成二进制按位与掩码算网络地址。IP 192.168.1.100 的最后一字节 100 写成二进制是 01100100;掩码最后一字节 192 是 11000000。按位与:01100100 & 11000000 = 01000000,也就是十进制 64。所以网络地址是 192.168.1.64。这一步用 Python 表示就是:
1 | # 计算网络地址:IP 和掩码按位与 |
第三步,算广播地址。广播地址 = 网络地址的主机位(后 6 位)全置 1。网络地址 192.168.1.64 的最后一字节 64 是 01000000,把后 6 位全置 1 得 01111111,也就是十进制 127。所以广播地址是 192.168.1.127。
第四步,算可用主机范围。可用主机从”网络地址 +1”到”广播地址 -1”,所以是 192.168.1.65 到 192.168.1.126。
第五步,算可用主机数。主机位有 6 位,所以主机位组合数是 2^6=64,去掉网络号(全 0,对应 192.168.1.64)和广播地址(全 1,对应 192.168.1.127),可用主机数 = 64 - 2 = 62 台。
总结一下这道题的答案:网络地址 192.168.1.64、广播地址 192.168.1.127、可用主机范围 192.168.1.65 ~ 192.168.1.126、可用主机数 62 台。整个计算套路就是这五步,再复杂的题也是这个流程,只是数字变一变。
再多走一个例子帮你巩固:给定 IP 10.10.100.200/20,求网络地址。
- 掩码 /20 表示前 20 位网络位,掩码前两字节是 255.255,第三字节是 11110000(即 240),第四字节是 0。所以掩码是 255.255.240.0。
- IP 第三字节 100 = 01100100,掩码第三字节 240 = 11110000,按位与 = 01100000 = 96。
- 网络地址 = 10.10.96.0。
你看,套路一致,只是把”算第几个字节”换了一下。/26 之类的非整 8 的掩码,核心就是看它落在第几个字节,只在那个字节做按位与,其他字节要么照抄(在掩码为 255 的字节)要么置 0(在掩码为 0 的字节)。
私有IP地址与NAT
私有 IP 地址范围(不能在公网路由,用于内网)必背:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。特殊地址:127.0.0.0/8 环回、0.0.0.0 本机所有地址、255.255.255.255 广播、169.254.0.0/16 自动私有地址(DHCP 拿不到地址时分配)。
为什么要专门留出私有 IP 地址段?因为 IPv4 地址总共只有约 43 亿个,地球上设备多得多,根本不够分。所以 IANA(互联网号码分配机构)留了三段私有地址给内网用:A 类留了 10.0.0.0/8(1600 多万个地址,大企业用),B 类留了 172.16.0.0/12(约 100 万个,中型网络用),C 类留了 192.168.0.0/16(约 6.5 万个,家庭和小公司用)。这些地址只能在局域网内部用,公网路由器看到这些地址的包直接丢弃,所以全世界的内网都能重复用同一批私有地址而不冲突——你家路由器是 192.168.1.1,我家也是,没关系,反正它们不出公网。
但内网的机器要访问公网怎么办?这时候 NAT(网络地址转换)就登场了。NAT 让内网多台机器共用一个公网 IP 出网。工作过程:
- 第一步:内网机器 192.168.1.10:54321 发起一个到公网服务器 8.8.8.8:80 的请求,包先到家里的 NAT 路由器。
- 第二步:路由器把这个包的源地址 192.168.1.10:54321 改成自己的公网地址,比如 1.2.3.4:60000(端口也换成一个空闲的高位端口),并把”192.168.1.10:54321 ↔ 1.2.3.4:60000”这条映射记在自己的 NAT 表里。
- 第三步:包带着伪装的源地址 1.2.3.4:60000 出去,到达 8.8.8.8:80。服务器以为是 1.2.3.4:60000 在跟它说话,根本不知道后面其实藏着一个 192.168.1.10。
- 第四步:服务器回包给 1.2.3.4:60000,路由器收到,查 NAT 表发现这条映射对应内网的 192.168.1.10:54321,于是把目的地址改回来转发给内网机器。
这就是 NAT 的核心:靠端口号区分”这个公网 IP 后面到底藏着哪台内网机器”,所以这种叫 NAPT(网络地址端口转换)更准确。一个公网 IP 理论上靠 65535 个端口能给几万台内网机器同时用,极大缓解了 IPv4 地址不够的问题。NAT 的副作用是破坏了端到端的直接通信——服务器没法主动发起连接到内网机器(因为 NAT 表里没有对应映射),所以 P2P 应用、内网穿透要专门处理。另外 NAT 还要改端口号,所以传输层的端口在 NAT 这一层被动了手脚,这也是为什么 NAT 通常被视为网络层和传输层之间的功能。
网络安全与状态管理
讲网络绕不开安全和状态。HTTP 本身是无状态的,但 Web 应用需要”记住”用户是谁、登录了没、购物车里有什么。怎么在无状态的协议上维持状态、又怎么保证状态不被恶意利用,就是这一节要讲的事。
同源策略与跨域CORS
同源策略是浏览器最基本的安全防线。它的意思是:协议、域名、端口三者必须完全相同,浏览器才允许一个页面访问另一个页面的 Cookie、DOM 等资源。比如 http://a.com 的页面想读 https://a.com 的 Cookie,协议不同,浏览器拦;http://a.com 想读 http://b.com 的 DOM,域名不同,浏览器拦;http://a.com:3000 想访问 http://a.com:8080 的接口,端口不同,浏览器也拦。这是为了防止恶意网站窃取你在其他网站的登录态和数据——如果没有同源策略,你打开一个钓鱼网站,它就能读到你刚登录过的银行网站的 Cookie,钱就没了。
但现代开发里前后端分离是常态,前端跑在 http://localhost:3000,后端跑在 http://localhost:8080,这本身就构成了跨域。浏览器会拦跨域请求,除非后端通过 CORS(跨源资源共享)明确允许。CORS 是服务器通过响应头告诉浏览器”我同意这个来源访问我”的机制。
CORS 把请求分两类:简单请求和预检请求。简单请求要同时满足几个条件——方法是 GET、HEAD 或 POST,且 Content-Type 只能是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 这三种之一,且不设置自定义头部。满足这些条件的请求,浏览器直接发出去,然后检查响应头里的 Access-Control-Allow-Origin 字段是否允许当前来源,允许就放行,不允许就拦截。预检请求针对的是不满足上述条件的请求(比如 PUT、DELETE 方法,或者 Content-Type 是 application/json,或者带自定义头部),浏览器会先发一个 OPTIONS 请求问服务器”我能不能用这个方法、带这个头部来访问你”,服务器回”可以”,浏览器才发真正的请求。这个 OPTIONS 请求就是”预检”,相当于先敲门问能不能进,得到允许才正式进。
Session 与 Cookie
HTTP 是无状态的,但 Web 应用要”记住”用户登录了没、购物车里有什么。Cookie 和 Session 就是用来补这个缺的。
Cookie 是存在客户端的小块数据。服务器通过响应头里的 Set-Cookie 字段把 Cookie 写到浏览器里,浏览器之后每次请求同一个域都会自动带上 Cookie。Cookie 适合存一些不大的、客户端能读的信息,比如用户偏好设置、登录态的 Session ID。
Session 是存在服务器端的用户状态数据。客户端登录后,服务器创建一个 Session 对象存用户信息,给这个 Session 分配一个唯一的 Session ID,把这个 ID 通过 Cookie 发给浏览器。浏览器下次请求自动带上这个 Cookie,服务器读出 Session ID 找到对应的 Session,就知道这个请求是谁发的。Session 适合存敏感的、不能让客户端篡改的信息,比如用户角色、权限。
两者的核心区别就是存的位置:Cookie 在客户端,Session 在服务器端。Session 通常通过 Cookie 里的 Session ID 来关联客户端,但 Cookie 也可以独立用来存非敏感信息。一般实践中,登录态用 Session 存(安全),Session ID 通过 Cookie 传(方便)。
单台服务器时这套机制没问题,但网站一旦上了多台服务器做负载均衡,问题就来了:用户第一次请求被分到 A 服务器,A 创建了 Session;第二次请求被分到 B 服务器,B 没有这个 Session,用户就被踢出登录了。怎么在多台服务器之间共享 Session?有三种常见方案。
第一种是 Session 复制:服务器之间互相同步 Session 数据,每台都存全量。优点是简单,缺点是服务器多了之后同步开销大、有延迟,不适合大规模集群。
第二种是集中式存储:把所有 Session 存到一个共享存储里,比如 Redis,所有服务器都去这个共享存储读写。这是最常用的方案,Redis 本身性能高、支持过期时间,很适合做 Session 存储。
第三种是 Token(比如 JWT,JSON Web Token):彻底放弃服务器端 Session,改成把用户信息加密后生成一个 Token 发给客户端,客户端每次请求在请求头里带上 Token,服务器拿到 Token 验证签名通过就认。这种方案是”无状态”的——服务器不存任何会话信息,所以天然支持分布式,加机器不用迁移 Session。缺点是 Token 一旦签发在过期前没法主动让它失效(除非维护一个黑名单),而且 Token 里塞的信息多的话体积会比 Session ID 大。
其他重要概念
WebSocket
HTTP 是请求-响应模型,客户端不主动问,服务器不会主动答,所以做不了实时推送。WebSocket 就是为实时通信设计的,它提供全双工通道——客户端和服务器可以同时向对方发数据,像打电话一样,谁想说话谁就说,不用等对方问。
WebSocket 的建立过程挺巧妙:它先借 HTTP 的壳。客户端发一个 HTTP 请求,但带上 Upgrade: websocket 头,意思是”我想升级协议”;服务器同意就回 101 Switching Protocols,连接就从 HTTP 切换成 WebSocket 了。握手成功之后,这条连接就不再走 HTTP 协议,而是走 WebSocket 自己的二进制分帧协议。所以 WebSocket 和 HTTP 的关系是”借 HTTP 完成握手,握手后单飞”。
WebSocket 的典型应用场景是在线聊天、实时游戏、股票行情推送、协同编辑(比如多人同时改一份文档)。这些场景的共同点是对实时性要求高,服务器需要主动推数据而不是等客户端问。除了 WebSocket,还有 Server-Sent Events(SSE)做服务器单向推送、HTTP/2 的服务器推送用于推资源(不是全双工),但能做到双向实时通信的主流方案就是 WebSocket。
CDN
CDN(内容分发网络)解决的是”用户离服务器太远导致访问慢”的问题。它的思路是在全球各地部署很多节点服务器,把网站的静态资源(图片、CSS、JS)缓存到这些节点上。用户访问时,CDN 智能调度让用户去离他最近的节点取资源,缩短了传输距离,自然就快了。好比一家全国连锁的快递公司在每个城市都建仓库,用户从最近的仓库取货,不用都从总部发货。
CDN 的好处有三个:一是降低延迟,用户就近取资源,响应快;二是减轻源站压力,大部分请求被 CDN 节点挡掉了,源服务器不用扛全部流量;三是能抵御部分 DDoS 攻击,攻击流量被 CDN 节点分散吸收,不会全部打到源站。个人博客也常用 CDN 加速图片和样式文件,提升访问速度。
负载均衡
当一台服务器扛不住全部流量时,就得多台服务器分担,怎么把请求合理地分发到多台服务器上,就是负载均衡做的事。负载均衡分两层:四层和七层。
四层负载均衡(比如 LVS)工作在传输层,只看 IP 和端口来转发请求,效率高,但不关心应用层内容。它就像快递分拣只看地址不看包裹里是什么。七层负载均衡(比如 Nginx)工作在应用层,能基于 HTTP、HTTPS 等协议做决策,可以处理 SSL 卸载、URL 路由、缓存等,更灵活但开销也更大。它就像分拣员不仅看地址还看包裹内容来决定怎么送。实际中常用组合是四层做入口分发、七层做应用层路由。
负载均衡的常见算法有三个。轮询是最简单的,按顺序一台一台轮流分配请求,公平但不考虑服务器负载差异。最少连接是把请求分给当前连接数最少的那台,比较智能,能避开忙的机器。IP 哈希是根据客户端 IP 算一个哈希值,保证同一个 IP 的请求总发给同一台服务器,这样能保持会话——用户第一次访问落到 A 服务器,之后还是 A 服务器,Session 不会丢。但 IP 哈希的问题是如果某段 IP 流量特别大,会导致负载不均。
RESTful API设计原则
REST(表述性状态转移)是一套 API 设计风格,RESTful API 就是按这套风格设计的接口。它的核心原则有三条。
第一条,用 URL 表示资源。资源是名词,URL 应该指向”东西”而不是”动作”。比如 /users/123 表示用户 123 这个资源,/users/123/orders 表示这个用户的订单列表。不该把动作写进 URL,比如 /getUser?id=123 或者 /deleteUser?id=123 就不 RESTful,因为它们把”做什么”也塞进了 URL。
第二条,用 HTTP 方法表示对资源的操作。GET 表示获取(读),POST 表示创建(新增),PUT 表示更新(整体替换),DELETE 表示删除。这样 URL 只描述”是什么”,方法描述”做什么”,分工清晰。配合状态码返回结果:200 成功、201 创建成功、404 资源不存在、400 请求格式错等。
第三条,无状态。每个请求必须包含服务器处理它所需的全部信息,服务器不保存客户端的会话状态。这意味着任何请求都可以发给任何一台服务器,结果都一样,天然适合分布式。这一条和上面讲的 Token 方案是配套的——Token 把状态存在客户端,服务器无状态,正是 RESTful 的体现。
计算机网络知识速记
OSI 七层从下到上”物数网传会表应”,对应的设备依次是中继器/集线器、交换机/网桥、路由器、网关/防火墙——交换机和路由器最容易记混,交换机工作在数据链路层靠 MAC 地址转发,路由器工作在网络层靠 IP 地址转发。数据封装的”加头加头加头”过程要会,发送方从上到下加,接收方从下到上剥,一层对应一层。TCP/IP 四层模型更贴近现实,会话层和表示层基本并入应用层。
TCP 三次握手必须记牢:第一次 SYN 客户端 seq=x,第二次 SYN+ACK 服务器 seq=y ack=x+1,第三次 ACK 客户端 seq=x+1 ack=y+1。三次不是两次是为了双向确认能力和防止旧连接请求。四次挥手要记住 TIME_WAIT 在主动关闭方那一边、等 2 个 MSL,作用是确保最后一个 ACK 到达对方、让旧报文消亡。看到”TIME_WAIT 出现在被动关闭方”是错的,被动关闭方是 CLOSE_WAIT。
TCP 可靠性机制四件套:序号确认、重传、流量控制(滑动窗口)、拥塞控制(慢启动、拥塞避免、快重传、快恢复)。滑动窗口管接收方扛不扛得住、由 rwnd 控制;拥塞控制管网络扛不扛得住、由 cwnd 控制,实际发送窗口 = min(rwnd, cwnd)。慢启动指数增长、拥塞避免线性增长,3 个重复 ACK 触发快重传只回到 ssthresh 一半、超时则 cwnd 回到 1——两种拥塞信号恢复策略不同,这个对比要分清。
HTTP 报文分四部分:请求行或状态行、头部、空行、主体。HTTP 方法幂等性:GET、PUT、DELETE 幂等,POST 不幂等。状态码 401 是未认证(没登录或登录失效)、403 是已认证但无权限(登录了但没权限)、404 是资源不存在——三个码最容易混,一定要分清。301 永久重定向、302 临时重定向、304 缓存未变。5xx 里 500 内部错误、502 网关错误、503 服务不可用、504 网关超时。HTTP 缓存分强缓存(Expires、Cache-Control,不问服务器直接用本地)和协商缓存(Last-Modified/If-Modified-Since、ETag/If-None-Match,过期后问服务器有没有变,没变回 304)。
HTTPS = HTTP + SSL/TLS,默认端口 443。握手核心是”非对称加密交换对称密钥,对称加密传数据”——非对称加密慢但安全、对称加密快但密钥分发难,混着用各取所长。客户端发 client_random、服务器发 server_random 和证书、客户端验证证书后用服务器公钥加密 pre_master_secret 发过去、双方用三个随机数算出对称会话密钥。SSL 2.0/3.0 已废弃,主流是 TLS 1.2 和 TLS 1.3。HTTP 协议演进:HTTP/1.1 有持久连接和管道化但有队头阻塞,HTTP/2 用多路复用、头部压缩、服务器推送解决,HTTP/3 改用基于 UDP 的 QUIC 进一步减少握手延迟。
DNS 解析层层递进:浏览器缓存→操作系统缓存和 hosts 文件→本地 DNS 服务器→根 DNS→顶级域 DNS→权威 DNS。客户端到本地 DNS 是递归查询(你替我问到底),本地 DNS 到外面是迭代查询(告诉我下一步问谁)。DNS 还能做负载均衡,把同一域名对应多个 IP 实现流量分发。
同源策略要求协议、域名、端口三者相同,浏览器才允许跨页面访问 Cookie 和 DOM。跨域用 CORS,简单请求直接发并检查响应头,预检请求先发 OPTIONS 问服务器允不允许。Cookie 存客户端、Session 存服务器端,Session 靠 Cookie 里的 Session ID 关联。分布式 Session 三种方案:Session 复制(同步开销大)、集中式存储(Redis 最常用)、Token/JWT(无状态,天然支持分布式)。
IP 分类看第一段数字:1-126 是 A 类、127 环回、128-191 是 B 类、192-223 是 C 类、224-239 是 D 类组播、240-255 是 E 类保留。私有地址三段必须背:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。特殊地址:127.0.0.0/8 环回、0.0.0.0 本机所有地址、255.255.255.255 广播、169.254.0.0/16 自动私有(DHCP 失败时分配)。
子网划分五步走:算掩码→IP 和掩码按位与得网络地址→网络地址主机位置 1 得广播地址→网络地址+1 到广播地址-1 是可用主机范围→2^(32-n)-2 是可用主机数,减的 2 是网络号和广播。CIDR 用 /n 表示掩码位数不绑定 A/B/C 分类,NAT 让内网共用一个公网 IP 出网、靠端口号区分内部机器。
TCP vs UDP 应用场景:HTTP/HTTPS、FTP、SMTP、SSH 用 TCP 因为要可靠;DNS 查询、视频直播、语音通话、游戏、DHCP 用 UDP 因为要快能容忍丢包。看到”DNS 一定用 UDP”是错的,区域传送用 TCP;”HTTP 一定用 TCP”在 HTTP/3 之前成立,HTTP/3 改用基于 UDP 的 QUIC。
其他重要概念:WebSocket 借 HTTP 握手后切到全双工协议,适合实时通信;CDN 把静态资源缓存到全球节点让用户就近取,降低延迟、减轻源站压力、抗 DDoS;负载均衡分四层(看 IP 端口)和七层(看应用层内容),常见算法有轮询、最少连接、IP 哈希;RESTful API 三原则是 URL 表示资源、HTTP 方法表示操作、无状态。