计算机网络
2025-4-6
| 2025-4-9
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password

宏观的大结构:

想象一下你要寄送一个包裹(比如一件网购的商品)给远方的朋友。这个过程其实和计算机网络传输数据非常相似,可以分成几个明确的步骤和角色,对应TCP/IP的各个层:
 
  1. 应用层 (Application Layer) - 你要寄送的“物品本身”和“寄件意图”
      • 做什么? 这是你直接接触和使用的层。它决定了你要传输什么内容,以及为什么要传输。比如,你想发送一封电子邮件、浏览一个网页、进行一次视频通话,或者传输一个文件。
      • 包裹比喻: 这就是你要寄送的商品本身(比如一本书、一件衣服)以及你写好的便签(比如“生日快乐!”)。不同的应用(邮件、网页、视频)就像不同类型的包裹内容和寄送目的。
      • 关键点: 关注的是数据的内容和用途
  1. 传输层 (Transport Layer) - “打包”和选择“邮寄方式”
      • 做什么? 这一层负责在你电脑上的特定程序(比如你的浏览器)和对方电脑上的特定程序(比如网站服务器)之间建立一个可靠的(或快速的)连接,并确保数据段的正确排序和完整性(或者不保证,看选择)。它给数据加上“端口号”,就像在地址后面加上“收件部门”或“房间号”,确保交给正确的应用程序。
      • 包裹比喻: 你把商品和便签装进一个合适的箱子(打包)。然后,你要选择邮寄方式:是选需要签收、可追踪、保证送达的快递(类似TCP协议,可靠),还是选速度快但不保证一定送到、可能丢失的平邮(类似UDP协议,高效)?你还要在包裹上写清楚是寄给“小明收”,而不是他家里的其他人(指定端口号)。
      • 关键点: 关注的是端到端(程序到程序)的传输可靠性、流量控制和端口
  1. 网络层 (Internet Layer / Network Layer) - “写地址”和“规划路线”
      • 做什么? 这一层负责在整个网络中找到从源头到目的地的最佳路径。它使用IP地址(就像街道地址)来标识网络中的每一台计算机,并决定数据包(包裹)应该走哪条路(通过哪个路由器/中转站)。
      • 包裹比喻: 你在打包好的箱子上写上完整的收件人地址和发件人地址(IP地址)。邮政系统(路由器网络)会根据这个地址,决定这个包裹应该先送到哪个城市的处理中心,再转到哪个区,等等,规划出一条跨越不同城市和地区的路线
      • 关键点: 关注的是IP地址寻址和跨网络的路由选择
  1. 网络接口层 (Network Interface Layer / Link Layer) - “交给快递员”和“实际运输工具”
      • 做什么? 这是最底层,负责处理物理网络上的数据传输。它将网络层的数据包封装成“帧”,加上物理地址(MAC地址,就像你家门牌号,只在小区内或同一栋楼内有效),并通过具体的物理媒介(如网线、光纤、Wi-Fi信号)发送出去。它处理的是同一局域网内(比如你家里的Wi-Fi网络,或者办公室网络)设备之间的直接通信。
      • 包裹比喻: 你把写好地址的包裹交给上门的快递员(网络接口)。快递员(或者说从你家到本地快递站点的这段路)知道怎么在你这个小区或这条街道上找到你家(MAC地址)。然后包裹会被装上具体的运输工具(卡车、飞机、货船,对应网线、Wi-Fi信号等物理介质),开始实际的物理移动,先送到本地的集散点。
      • 关键点: 关注的是物理地址(MAC地址)、局域网内的帧传输和具体的物理介质
 
 
整个过程串联起来:
当你发送数据时(比如发邮件):
  1. 应用层:写好邮件内容。
  1. 传输层:给邮件数据打包(加上TCP/UDP头部,包含端口号),选择可靠的TCP方式。
  1. 网络层:在传输层的数据包外面再套一层(加上IP头部,包含目标IP地址和源IP地址),规划好去往目标邮件服务器的大致路线。
  1. 网络接口层:在网络层的数据包外面再套一层(加上MAC头部,包含下一跳路由器的MAC地址或目标主机的MAC地址),通过网线或Wi-Fi发送出去。
数据到达对方电脑时,过程正好相反,像层层拆开包裹
  1. 网络接口层:接收物理信号,检查MAC地址,去掉MAC头部,把数据包交给网络层。
  1. 网络层:检查IP地址,去掉IP头部,把数据包交给传输层。
  1. 传输层:检查端口号,根据TCP/UDP头部信息处理数据(比如重组数据段、确认收到),去掉TCP/UDP头部,把数据交给应用层。
  1. 应用层:接收到原始的邮件内容,呈现给收件人。
核心思想:
  • 分层解耦: 每一层只关心自己的任务,不需要知道其他层的具体实现细节。就像快递员不需要知道包裹里是什么,只需要看地址送货;邮政系统规划路线时,不关心是用卡车还是飞机运输。
  • 标准化: 每一层都有标准的协议(规则),保证不同厂商的设备和软件能够互相通信。
  • 封装与解封装: 数据在发送时从上到下逐层添加头部信息(封装),在接收时从下到上逐层移除头部信息(解封装)。
 

应用数据 (邮件内容) -> [传输层加上 TCP/UDP 头(含端口号)] -> [网络层再加上 IP 头(含 IP 地址)] -> [网络接口层再加上 MAC 头(含 MAC 地址)和尾部校验] -> 变成比特流在网线/空中传输。
接收方则反过来,一层层地“拆开”这些头部信息,最终将原始的应用数据交给目标应用程序。每一层都依赖下一层提供的服务,并为上一层提供服务。
 
 
 
 
 
 
 

1. 应用层 (Application Layer) - “包裹里的具体内容和寄送服务的类型”

  • 核心任务: 处理特定应用程序的通信需求,定义我们能“看到”和“使用”的网络服务规则。
  • 通俗解释: 这一层决定了你要用网络来干什么。是想发一封电子邮件?还是想看一个网页?或者是进行文件传输?或者解析一个域名(比如把 www.google.com 变成 IP 地址)?不同的应用场景,就有不同的规则(协议)。
  • 包裹比喻:
    • 你想寄的是一封信件(对应邮件协议 SMTP/POP3/IMAP)。
    • 你想请求一本商品目录册(对应网页协议 HTTP/HTTPS)。
    • 你想寄送一个大箱子里的文件(对应文件传输协议 FTP)。
    • 你想查询“小明家”的具体地址在哪条街(对应域名解析协议 DNS)。
  • 主要协议举例: HTTP (网页), HTTPS (安全网页), SMTP (发邮件), POP3/IMAP (收邮件), FTP (文件传输), DNS (域名解析), Telnet (远程登录) 等。
  • 数据单位: 通常称为 消息 (Message) 或直接就是 数据 (Data)
 
 

Http

 
HTTP 是什么?
  • 名字: 超文本传输协议 (Hypertext Transfer Protocol)。
  • 本质: 互联网上应用最广泛的一种网络协议(就是一套通信规则)。
  • 作用: 它是客户端 (Client)(比如你的浏览器)和服务器 (Server)(比如存放网站内容的服务器)之间进行请求和响应的标准。主要用于从万维网服务器传输超文本标记语言(HTML)页面、图片、文件等资源。
  • 简单说: HTTP 就是浏览器和网站服务器之间沟通的“普通话”
 
 
 
核心工作方式:请求-响应模型 (Request-Response)
  1. 客户端发起请求 (Client sends Request): 你的浏览器想看一个网页或图片,就会按照 HTTP 协议的格式,打包一个“请求”消息发给服务器。
  1. 服务器处理请求 (Server processes Request): 网站服务器收到这个请求,理解你想干什么(比如想要哪个页面的数据)。
  1. 服务器返回响应 (Server sends Response): 服务器处理完后,同样按照 HTTP 协议的格式,打包一个“响应”消息发回给浏览器。这个响应里可能包含请求的资源(HTML 代码、图片数据等),或者一个说明(比如“你找的东西不存在”)。
 
 
  1. 客户端-服务器 (Client-Server): 总是由客户端主动发起请求,服务器被动响应。服务器一般不会主动给客户端发消息。
  1. 无状态 (Stateless): 这是 HTTP 的一个核心特点!服务器默认不记录任何关于客户端上一次请求的信息。每个请求都是独立的。
      • 好处: 服务器不用维护大量状态信息,设计简单,更容易扩展(处理更多用户)。
      • 如何保持状态? 实际应用中(如购物车、登录状态),需要通过 CookiesSession 等技术来“记住”用户状态。但这不是 HTTP 协议本身的功能,而是基于 HTTP 的扩展机制。
      • 比喻: 就像一个记性不好的客服,每次你打电话过去,都得重新告诉他你是谁、你上次咨询了什么,除非他用了客户管理系统(Cookies/Session)做了记录。
 
 
HTTP 报文结构 (请求和响应长什么样? - 简化版):
一个 HTTP 消息(无论是请求还是响应)通常由三部分组成:
  1. 起始行 (Start Line):
      • 请求行: 包含 请求方法 (Method) + 请求 URL + HTTP 版本
        • GET /index.html HTTP/1.1 (意思是:我想用 GET 方法获取 /index.html 这个资源,用的是 HTTP/1.1 协议)
      • 状态行 (响应才有): 包含 HTTP 版本 + 状态码 (Status Code) + 状态描述
        • HTTP/1.1 200 OK (意思是:服务器用 HTTP/1.1 协议回复你,状态码是 200,表示成功)
  1. 首部 / 头部 (Headers):
      • 包含很多键值对,用来传递额外的重要信息。
      • 请求头例子: Host: www.example.com (我想访问的主机), User-Agent: Chrome/123 (我的浏览器类型), Accept-Language: zh-CN (我希望优先看到中文内容), Cookie: ... (携带之前服务器给我的身份小饼干)。
      • 响应头例子: Content-Type: text/html (我发给你的是 HTML 文本), Content-Length: 1024 (数据长度是 1024 字节), Set-Cookie: ... (给你一个身份小饼干下次带来), Cache-Control: no-cache (这个响应不要缓存)。
  1. 主体 / 正文 (Body):
      • 可选部分。真正要传输的数据就在这里。
      • 请求体: 比如你用 POST 方法提交表单时,用户名密码等数据就在请求体里。GET 请求通常没有请求体。
      • 响应体: 服务器返回的 HTML 代码、图片数据、JSON 数据等就在响应体里。
常用请求方法 (Methods - 你想让服务器干嘛?):
  • GET: 获取资源。(最常用)
  • POST: 提交数据让服务器处理(比如创建新用户、提交表单)。(常用)
  • PUT: 替换服务器上的资源(用请求体里的数据完整替换目标资源)。
  • DELETE: 删除服务器上的资源。
  • HEAD: 和 GET 类似,但只获取响应头,不要响应体(用于检查资源是否存在、是否修改等)。
  • OPTIONS: 询问服务器支持哪些请求方法。
 
GET 的语义是请求获取指定的资源。GET 方法是安全、幂等、可被缓存的。
POST 的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST 不安全,不幂等,(大部分实现)不可缓存。
 
 
http的缓存技术:
 
核心机制是服务器通过响应头 (Cache-Control, Expires, ETag, Last-Modified) 控制缓存行为。
 
  • 新鲜度 (Freshness / Expiration): 决定多久内可以直接用缓存 (max-age)。
  • 验证 (Validation): 缓存过期后如何向服务器确认缓存是否仍有效 (If-Modified-Since, If-None-Match)。
 
 
freshness:
  • 概念: 缓存的资源能在多长时间内被认为是“新鲜”的,可以直接使用而无需询问服务器
  • 主要控制头:
    • Cache-Control (首选): 这是目前最主要、最灵活的缓存控制头。它包含很多指令:
      • max-age=<秒数>: 指定资源能被视为新鲜的最长持续时间(从响应生成时开始计算)。例如 Cache-Control: max-age=3600 表示这个资源在接下来 1 小时内都是新鲜的,可以直接用缓存。
      • public: 表明响应可以被任何缓存(包括浏览器、CDN 等共享缓存)缓存。
      • private: 表明响应只能被单个用户的浏览器缓存,不能被共享缓存缓存(比如包含用户信息的 HTML 页面)。
      • no-cache: 注意:不是“不缓存”,而是**“每次使用缓存前必须去服务器验证一下资源是否仍然有效”**。详见下面的“验证”部分。
      • no-store: 这个才是“完全不缓存”。浏览器和所有中间缓存都不得存储这个响应的任何部分。通常用于敏感数据。
 
  • 工作流程: 如果浏览器发现缓存里的资源还在“保质期”内(max-age 没过),就直接从缓存加载,速度飞快!
 
 
validation:
概念:如果缓存的资源超过了保质期max-age 过了),或者压根没有保质期信息,或者设置了 no-cache,浏览器就不能直接使用这个缓存了。但它也不会傻傻地直接重新下载整个资源,而是会先去服务器验证一下它手里的这个“过期货”是不是其实还能用
 
主要机制 (通过请求头发送验证信息)
  • 基于最后修改时间:
    • 服务器首次响应时带上:Last-Modified: <文件最后修改日期>
    • 浏览器验证时带上请求头:If-Modified-Since: <上次收到的最后修改日期> (意思是:这个日期之后文件修改过吗?)
  • 基于 ETag (实体标签 - 更精确):
    • 服务器首次响应时带上:ETag: "一个独一无二的版本标识符" (比如文件内容的哈希值)
    • 浏览器验证时带上请求头:If-None-Match: "上次收到的那个ETag" (意思是:这个资源的 ETag 还是不是这个值?)
    • ETag 更好,因为它能检测到文件内容变化,即使修改日期没变(比如替换了内容相同但时间戳更新的文件)。
 
服务器的响应:
  • 如果资源没变: 服务器会返回一个非常小的 304 Not Modified 响应(状态码 304,没有响应体 Body)。浏览器收到 304 就知道:“哦,我缓存的版本还能用!” 于是就加载缓存的版本。这大大节省了带宽!
  • 如果资源变了: 服务器会返回一个正常的 200 OK 响应,包含全新的资源内容可能更新的缓存头。浏览器就用这个新版本,并更新缓存
 
notion image
 
 
重要状态码 (Status Codes - 服务器告诉你结果如何?):
记住主要类别和几个常见代码:
  • 1xx (信息性): 收到请求,继续处理。(不常见)
  • 2xx (成功): 请求已成功被服务器接收、理解、并接受。
    • 200 OK: 请求成功。(最常见)
  • 3xx (重定向): 需要后续操作才能完成请求。
    • 301 Moved Permanently: 请求的资源已永久移动到新 URL。
    • 302 Found: 请求的资源临时移动到新 URL。
    • 304 Not Modified: 资源未修改,可使用缓存的版本。
  • 4xx (客户端错误): 请求包含语法错误或无法完成请求。
    • 400 Bad Request: 请求无效 (比如格式错误)。
    • 401 Unauthorized: 未授权 (需要登录认证)。
    • 403 Forbidden: 服务器理解请求,但拒绝执行 (权限不足)。
    • 404 Not Found: 找不到请求的资源。(非常常见)
  • 5xx (服务器错误): 服务器在处理请求的过程中发生了错误。
    • 500 Internal Server Error: 服务器内部错误。(常见)
    • 503 Service Unavailable: 服务器暂时过载或维护。
 
 
HTTPS 是什么?
  • HTTPS = HTTP + SSL/TLS (安全套接层/传输层安全协议)。
  • 简单说,就是在 HTTP 传输之前,先用 SSL/TLS 对通信内容进行加密,并在通信双方之间验证身份
  • 解决了 HTTP 的两大问题:
    • 数据没加密(不安全): 中途可能被窃听。HTTPS 加密了。
    • 身份没验证(不安全): 可能访问了假冒的网站。HTTPS 通过证书验证服务器身份。
  • 现在网站基本都强制使用 HTTPS
如何保护信息
想象一下 HTTPS 就是给普通的 HTTP 通信加了一把安全锁。这把锁主要通过以下三个关键机制来保护你的信息:
  1. 加密 (Encryption) - 防止偷听
      • 做什么? 把你和网站之间传输的数据(比如密码、银行卡号)变成一堆乱码。
      • 怎么做? 双方会先用一种复杂的方式(非对称加密)商量好一个只有你们俩知道的“暗号”(对称密钥)。之后的所有通信都用这个“暗号”来加密和解密。
      • 效果: 就算有黑客在中间截获了数据,看到的也只是一堆无意义的乱码,无法得知原始内容。就像你用密码锁锁住了箱子,不知道密码的人打不开。
  1. 身份验证 (Authentication) - 防止假冒
      • 做什么? 确认你正在访问的网站是真的,而不是一个伪装的钓鱼网站。
      • 怎么做? 网站需要向一个权威的第三方机构(证书颁发机构,CA)申请一个“身份证”,叫做 SSL/TLS 证书。你的浏览器在访问网站时,会检查这个证书是不是由可信的机构颁发的、有没有过期、是不是给这个网站的。
      • 效果: 就像你去银行,需要看银行工作人员的工牌确认身份一样,浏览器通过检查证书来确认网站的“身份”,防止你被骗到假网站。
  1. 数据完整性 (Integrity) - 防止篡改
      • 做什么? 确保数据在传输过程中没有被偷偷修改。
      • 怎么做? 数据在发送前会生成一个“指纹”(消息认证码,MAC)。接收方收到数据后,会用同样的方法再算一次“指纹”,然后比较两个“指纹”是否一致。
      • 效果: 如果数据在传输中被改动了,那么计算出的“指纹”就会不一样,接收方就能立刻发现数据被动过手脚了。就像快递箱上的封条,如果封条破了,你就知道里面的东西可能被动过了。
 
 
https一定可靠吗?
不,HTTPS 并不能保证绝对的安全可靠,但它极大地提高了网络通信的安全性,是目前保护网络传输安全的标准和基础
把它想象成给你的房子装了一把非常坚固的防盗门锁(HTTPS),这比没有锁(HTTP)安全得多,但并不能防御所有类型的风险。
以下是为什么 HTTPS 不等于绝对安全的原因:
  1. 网站本身可能不安全:
      • 服务器漏洞: 即使通信是加密的,如果网站服务器本身存在安全漏洞(比如 SQL 注入、XSS 跨站脚本攻击),黑客仍然可能窃取存储在服务器上的数据,或者在网站上植入恶意代码。HTTPS 只保护传输过程,不保护服务器本身。
      • 网站内容可能是恶意的: 一个钓鱼网站或包含恶意软件的网站也可以使用 HTTPS。浏览器地址栏的“锁”标志仅仅表示你和这个网站之间的连接是加密和经过验证的,并不代表这个网站的内容是善意或安全的。你仍然可能被诱骗输入敏感信息或下载病毒。
  1. 证书不能保证网站信誉:
      • 域名验证 (DV) 证书很容易获取: 最基础的 SSL/TLS 证书(DV 证书)只验证申请者对域名的控制权,并不严格审查申请者的真实身份或商业信誉。因此,诈骗分子也可以为他们的钓鱼网站申请到有效的 HTTPS 证书。
      • 忽略证书警告: 如果用户在浏览器弹出证书错误警告时选择“继续访问”,那么 HTTPS 提供的身份验证保护就失效了。
  1. 客户端(你的电脑/手机)可能不安全:
      • 恶意软件/病毒: 如果你的设备感染了病毒或木马,它们可以在数据被 HTTPS 加密之前(比如在你键盘输入时)或解密之后(在浏览器显示时)窃取你的信息。
      • 不安全的网络环境: 在某些极端情况下(例如,被强制安装了恶意的根证书),中间人攻击仍然可能发生。
  1. 协议或实现本身可能存在漏洞:
      • 虽然很少见,但 SSL/TLS 协议本身或其具体实现(比如某个软件库)偶尔会被发现存在漏洞(如过去的 Heartbleed 漏洞),需要及时更新打补丁。
      • 配置错误: 服务器管理员如果错误地配置了 HTTPS(比如使用了过时或不安全的加密算法),也会降低安全性。
 
 
 
好的,我们来简洁清晰地比较一下 HTTP/1.1, HTTP/2, 和 HTTP/3 的主要区别:
HTTP/1.1 (老大哥 - 沿用至今的基础版)
  • 特点:
    • 基于 TCP 协议。
    • 文本格式传输请求和响应头。
    • 请求-响应模型: 通常一个连接一次处理一个请求,响应回来后才能处理下一个(有流水线技术 Pipelining 但问题多,基本不用)。
  • 主要问题:
    • 队头阻塞 (Head-of-Line Blocking): 同一个 TCP 连接上,如果第一个请求的响应没回来,后面的请求就算处理完了也得等着。浏览器通常开多个 TCP 连接 (比如 6 个) 绕过这个问题,但开销大。
  • 比喻: 单车道。一次只能跑一辆车(请求),后面的车得等前面的过去。
 
 
HTTP/2 (中生代 - 性能优化版)
  • 目标: 解决 HTTP/1.1 的性能瓶颈。
  • 主要改进:
    • 仍然基于 TCP 协议。
    • 二进制格式: 解析更高效。
    • 多路复用 (Multiplexing): 可以在一个 TCP 连接同时发送多个请求和接收多个响应,响应可以不按顺序到达。解决了 HTTP 层面的队头阻塞。
    • 头部压缩 (Header Compression - HPACK): 减少请求头的大小,节省带宽。
    • 服务器推送 (Server Push): 服务器可以主动推送资源(如 CSS, JS)给客户端,无需客户端额外请求。
  • 遗留问题:
    • 虽然解决了 HTTP 层面的队头阻塞,但底层的 TCP 协议本身仍然存在队头阻塞。如果一个 TCP 包丢失,整个连接上的所有请求流都得等这个包重传,即使其他流的数据已经到了。
  • 比喻: 把单车道升级成了多车道高速公路 (但路面材质还是 TCP)。可以在同一条路上同时跑多辆车(请求/响应并行)。但如果路上某个地方出了个小事故(TCP 丢包),整条高速公路都可能堵一下
 
HTTP/3 (新生代 - 彻底革新版)
  • 目标: 解决 HTTP/2 遗留的 TCP 队头阻塞问题,提升连接速度和稳定性。
  • 主要革新:
    • 不再基于 TCP,而是基于 QUIC 协议 (运行在 UDP 之上)。这是最核心的变化。
    • 彻底解决队头阻塞: QUIC 的流是独立的,一个流的数据包丢失不影响其他流的传输。
    • 更快的连接建立: QUIC 将 TCP 握手和 TLS (加密) 握手合并,减少了建立安全连接所需的往返时间 (0-RTT 或 1-RTT)。
    • 内置加密: 加密是 QUIC 的一部分,强制执行,更安全。
    • 连接迁移 (Connection Migration): 当你的网络变化时(比如从 Wi-Fi 切换到 4G),连接可以保持不断开,体验更流畅。
  • 比喻: 不再用原来的高速公路 (TCP),而是换了一套全新的、更先进的交通系统 (QUIC/UDP),比如像是多条独立的磁悬浮轨道。一条轨道出问题(丢包),其他轨道照常运行。上车(连接建立)更快,安检(加密)是标配,还能无缝换乘(连接迁移)。
总结:
特性
HTTP/1.1
HTTP/2
HTTP/3
底层协议
TCP
TCP
QUIC (基于 UDP)
队头阻塞
HTTP层面 & TCP层面
TCP层面存在
基本解决
多路复用
无 (或 Pipelining)
有 (QUIC 流更独立)
传输格式
文本
二进制
二进制
头部压缩
HPACK
QPACK (适配 QUIC)
连接建立
较慢
较慢
更快 (0/1-RTT)
加密
可选 (HTTPS)
理论可选 (实际必需 HTTPS)
强制内置
主要目标
基础通信
提升性能 (多路复用等)
解决 TCP 瓶颈, 提升速度/可靠性
 
 
为什么有了http还要websocket
 
是因为 HTTP 在某些场景下“不够给力”,特别是处理需要“实时、双向”通信的需求时
我们先回顾一下 HTTP 的特点(尤其是 HTTP/1.1 和 HTTP/2,它们都基于 TCP):
  • 请求-响应模式 (Request-Response): 必须是客户端先发起请求,服务器才能响应。服务器不能主动向客户端推送信息。
  • 单向性: 数据流主要是从服务器到客户端(获取资源),或者一次性的从客户端到服务器(提交表单)。
  • 为了实时怎么办?(HTTP 的“笨办法”):
    • 轮询 (Polling): 客户端像个“急性子”,每隔很短时间(比如 1 秒)就主动问服务器:“有新消息吗?有新消息吗?”。即使没新消息也得问,非常浪费资源和流量。
    • 长轮询 (Long Polling): 客户端问服务器:“有新消息吗?”,服务器收到后“憋着”,不马上回答,直到真的有新消息了才回复客户端。客户端收到回复后,立刻再发一个同样的长轮询请求继续“憋着”等。这比轮询好点,但仍然有延迟(消息到达和下一次请求之间),且服务器需要维持连接,开销也不小。
这些“笨办法”在需要真正实时、频繁双向交流的场景下,效率低、延迟高。 比如:
  • 在线聊天室(你希望新消息立刻显示,而不是等几秒轮询一次)
  • 股票行情实时更新
  • 多人在线游戏(需要低延迟地同步玩家状态)
  • 协同编辑文档(比如 Google Docs)
  • 实时数据监控仪表盘
这时候,WebSocket 就闪亮登场了!
WebSocket 被设计出来就是为了解决 HTTP 在这些场景下的不足。它的核心优势在于:
  1. 真正的全双工通信 (Full-Duplex):
      • 一旦 WebSocket 连接建立成功,客户端和服务器之间就建立了一条持久性的、双向的通道
      • 双方都可以随时主动向对方发送数据,不需要等待对方的请求。就像建立了一条电话线,双方可以随时自由通话,而 HTTP 更像是寄信,必须你寄一封,我回一封。
  1. 更低的开销和延迟:
      • WebSocket 连接只需要一次初始握手(这个握手是借用 HTTP 协议完成的,请求头里包含 Upgrade: websocket)。
      • 握手成功后,后续的数据传输使用的是 WebSocket 自定义的、更轻量级的数据帧 (Frame),头部开销比每次都带一堆 HTTP Headers 小得多。这使得传输非常高效,延迟也更低。
  1. 持久连接:
      • 连接一旦建立,除非一方明确关闭或网络中断,否则会一直保持。避免了 HTTP (即使是 Keep-Alive) 需要为每个逻辑上的“推送”反复建立或管理连接状态的开销。
 
 
  • WebSocket 的“基因”就是为了实时、双向通信而生。 它提供了一个持久、低开销、全双工的通信通道。
  • 它们是互补关系,不是替代关系。
    • 获取网页、图片、文件等资源,进行一次性的表单提交,用 HTTP(及其各版本)仍然是最高效、最合适的。
    • 需要实时聊天、实时数据更新、在线游戏等场景,用 WebSocket 是更优的选择。
 
 
 
 
 
 
 
 

2. 传输层 (Transport Layer) - “选择快递公司和打包方式”

  • 核心任务: 在两个应用程序之间建立端到端的连接,管理数据传输的可靠性效率,并将大块数据分段
  • 通俗解释: 这一层不关心包裹具体内容是什么,只关心怎么把它安全、有序或快速地从你的应用程序(比如浏览器)送到对方的应用程序(比如网站服务器)。它负责“打包”数据,并选择合适的“运输服务”。
  • 包裹比喻:
    • 选择服务类型:
      • TCP (传输控制协议):顺丰或EMS快递,提供可靠服务。它会先打电话确认对方在不在家(建立连接),给每个小包裹编号(序列号),对方收到要签收确认(ACK),如果丢了会重寄(重传),还会根据路况调整速度(流量控制/拥塞控制)。虽然慢点,但保证送到,且顺序正确。适合网页、邮件、文件传输这种不能出错的应用。
      • UDP (用户数据报协议):普通平邮,只管把包裹扔进邮筒,不保证一定送到,也不保证顺序,速度快,开销小。适合视频会议、在线直播、DNS查询这种能容忍少量丢失(或者应用层自己会处理)且对实时性要求高的场景。
    • 端口号 (Port Number): 在包裹上写上“XX 公司 市场部收”或“XX 小区 3 号楼 101 室收”。端口号就是用来区分同一台电脑上不同应用程序的“房间号”,确保数据交给正确的程序处理(比如 Web 服务通常用 80/443 端口,邮件服务用 25 等)。
  • 数据单位: TCP 数据段称为 段 (Segment),UDP 数据段称为 数据报 (Datagram)
 
 
 

TCP

 
  1. 半连接(Half-Open Connection)
      • 发生在TCP三次握手的前两个步骤SYNSYN-ACK)。此时,服务器收到客户端的SYN包后,会将连接放入半连接队列(SYN Queue),等待客户端的ACK确认。
      • 此阶段连接未完全建立,资源占用较少,但可能受到SYN Flood攻击(恶意发送大量SYN包耗尽服务器资源)。
  1. 全连接(Established Connection)
      • 当三次握手完成(客户端发送ACK后),连接从半连接队列转移到全连接队列(Accept Queue),等待服务器调用accept()处理。
      • 此时连接已完全建立,双方可正常通信。
 
 
必须掌握的核心原理和机制(用“寄送重要合同”的比喻):
面向连接 (Connection-Oriented) - “先打个电话确认一下”
  • 原理: 在正式传输数据前,发送方和接收方必须先建立一个连接,确保双方都准备好了。
  • 机制:三次握手 (Three-Way Handshake)
    • 你 (发送方): “喂,老王(接收方),我想给你寄合同,你那边方便收吗?” (SYN - 同步请求)
    • 老王: “哎,方便方便!我也准备好收你合同了,你听到了吗?” (SYN-ACK - 同步确认+应答)
    • 你: “听到了听到了!那我这就开始寄了哈!” (ACK - 确认)
  • 有趣点: 像不像打电话确认?三次交互确保双方都知道对方在线且准备就绪,避免了“盲寄”的尴尬。
 
notion image
 
为什么三次握手就够了
为什么两次握手不够? (Why not two?)
想象一下只有两步:
  1. 我 -> 你: “喂,在吗?我想和你说话。” (发送 SYN)
  1. 你 -> 我: “在呢,说吧!” (回复 SYN-ACK)
问题出在哪?
  • 服务器无法确认客户端是否收到了它的“同意”: 服务器发出“在呢,说吧!” (SYN-ACK) 之后,它不知道客户端是否真的收到了这个回复。如果这个回复在路上丢了,客户端会认为连接没建立,可能会重试或者放弃。但服务器却认为连接已经“半建立”了,它会傻傻地等着客户端说话,甚至分配了资源。这就造成了服务器资源的浪费和状态不一致。
  • 无法处理“失效的连接请求”: 想象一个极端情况:
    • 我很早之前给你打过一个电话(发送了一个 SYN),但这个电话信号不好,在网络里绕了很久很久才到你那。
    • 我早就因为没收到回复而放弃了,甚至已经挂机了。
    • 现在,这个“迟到的”电话请求 (SYN) 突然到达了你那里。
    • 你一看,“哦,有人要跟我说话”,于是你回复“在呢,说吧!” (SYN-ACK)。
    • 因为只有两次握手,你回复之后就认为连接建立了,开始等待。
    • 但我(客户端)早就挂机了,根本不会理睬你的回复,或者收到回复后发现不是我当前想要的连接,会发送一个 RST(重置)报文。但服务器在你回复之后、收到 RST 之前,已经认为连接建立了,分配了资源。如果这种情况频繁发生(网络中充满了这种迟到的 SYN),服务器资源就会被大量无效的“半连接”耗尽。
两次握手的核心缺陷:服务器无法确认客户端是否已准备就绪。
为什么三次握手就够了? (Why three is enough?)
  1. 我 -> 你: “喂,在吗?我想和你说话。我的开场白是第 X 句。” (SYN, Seq=X)
      • 客户端证明自己能发送。
  1. 你 -> 我: “在呢!收到了你的第 X 句(所以我知道你能发,我也能收)。我也准备好了,我的开场白是第 Y 句。” (SYN-ACK, Seq=Y, Ack=X+1)
      • 服务器证明自己能收(收到了 SYN)、能发(发出了 SYN-ACK),并确认了客户端的起始序号。
  1. 我 -> 你: “收到!知道了你的开场白是第 Y 句。” (ACK, Ack=Y+1)
      • 客户端证明自己能收(收到了 SYN-ACK),并确认了服务器的起始序号。
三次握手的好处:
  • 双方确认: 通过这三步,客户端和服务器都确认了:
    • 自己能发。
    • 自己能收。
    • 对方能发。
    • 对方能收。
  • 同步初始序列号: 双方都知晓了对方的起始序列号(X 和 Y),为后续可靠传输(按顺序发送和确认)打下基础。
  • 防止失效连接请求: 在上面那个“迟到的 SYN”场景中:
    • 迟到的 SYN (Seq=X) 到达服务器。
    • 服务器回复 SYN-ACK (Seq=Y, Ack=X+1)。
    • 客户端收到这个 SYN-ACK 后,发现自己当前并没有发起这个连接(或者序列号对不上),它知道这是个过期的请求,就会发送一个 RST 报文给服务器。
    • 服务器收到 RST 后,就知道这个连接是无效的,会释放资源,不会傻等。 关键在于第三次握手,客户端的最终确认(ACK)或者拒绝(RST)给了服务器明确的信号。
为什么不需要四次握手? (Why not four?)
四次握手,通常是把第二次握手中的 SYN 和 ACK 分开:
  1. 我 -> 你:SYN
  1. 你 -> 我:ACK (确认收到 SYN)
  1. 你 -> 我:SYN (表明自己也准备好了)
  1. 我 -> 你:ACK (确认收到你的 SYN)
问题: 第二步和第三步完全可以合并!服务器在确认收到客户端的 SYN (ACK) 的同时,完全可以把自己的 SYN 一起发出去。没有必要分开成两步。合并成一步(SYN-ACK)更高效,减少了一次网络传输的延迟。
总结:
  • 两次握手不够: 服务器无法确认客户端是否收到自己的响应,容易造成资源浪费和处理失效连接请求的问题。
  • 三次握手正好: 刚好能够让双方都确认对方的收发能力,并同步初始序列号,同时能有效处理历史连接请求。是建立可靠连接所需的最少步骤。
  • 四次握手冗余: 可以实现同样目的,但效率更低,没有必要。
 
 
 
 
可靠传输 (Reliable Delivery) - “丢了?我补寄!顺序乱了?我帮你排!”
  • 原理: 确保数据不丢失、不重复、按顺序到达。
  • 机制:
    • 序号 (Sequence Numbers): TCP 把你要发送的数据想象成一本书,它会给书的每一页(数据段)编上页码(序号)。
    • 确认应答 (Acknowledgements - ACKs): 老王每收到一页或几页合同,就会给你回个信:“嘿,第 1 到 10 页我收到了!” (ACK)。这个 ACK 通常会告诉你它期望收到的下一页的页码。
    • 超时重传 (Timeout Retransmission): 你寄出第 11-20 页后,等了一段时间还没收到老王的确认信(可能信丢了,也可能合同路上丢了)。TCP 老司机不等了,直接把第 11-20 页重新寄一份!
    • 数据排序: 就算因为网络问题,第 30 页比第 25 页先到了老王那里,老王会根据页码(序号)把它们按正确顺序重新排列好,再交给上层应用(比如浏览器)。
  • 有趣点: 就像一个超负责的快递员,自带清单核对,丢了就补,乱了就理,保证合同完整无缺、顺序正确。
 
 
流量控制 (Flow Control) - “老王,你慢点寄,我信箱快满了!”
  • 原理: 防止发送方发送速度过快,导致接收方处理不过来而“爆仓”。
  • 机制:滑动窗口 (Sliding Window)
    • 老王 (接收方) 会在回信 (ACK) 里告诉你:“我的信箱(接收缓冲区)现在还能装 5 页合同 (窗口大小)”。
    • 你 (发送方) 就知道,在收到老王新的指示前,最多只能再寄 5 页。
    • 老王处理完一些合同,腾出空间了,就会在下次的回信里告诉你:“我现在能装 10 页了!” 你就可以适当加快速度。
  • 有趣点: 就像两人通话,一方说“你慢点说,我记不过来了”,另一方就会放慢语速。这是点对点的速度协调。
 
 
拥塞控制 (Congestion Control) - “妈呀,路上堵车了,所有人都慢点开!”
  • 原理: 当网络本身发生拥堵时(不是接收方处理不过来,而是中间的路堵了),TCP 会主动减慢发送速率,避免加剧网络拥堵,防止整个交通系统瘫痪。
  • 机制: 这比较复杂,但核心思想是 TCP 通过观察网络状况(比如丢包、延迟增加)来判断是否拥堵。
    • 慢启动 (Slow Start): 刚开始发送时,慢慢提速,试探网络容量。
    • 拥塞避免 (Congestion Avoidance): 速度到一定程度后,开始“温柔地”增加发送速率。
    • 快速重传 (Fast Retransmit) / 快速恢复 (Fast Recovery): 收到几个重复的 ACK(暗示某个包丢了),TCP 判断可能只是个别丢包,而不是严重拥堵,于是快速重传丢失的包,并适当降低速率,而不是一下子降到底。如果发生超时,那说明网络可能真堵得厉害,速率会大幅下降。
  • 有趣点: 像个有社会责任感的司机,发现路上堵车了,主动减速,而不是猛踩油门往前挤。这是 TCP 为整个互联网考虑的大局观!(区别于流量控制,流量控制是关心接收方,拥塞控制是关心整个网络)
 
 
面向字节流 (Byte Stream) - “别管我分几次寄,你看成一整条信息就行”
  • 原理: TCP 不关心你应用层交下来的数据块有多大,它会把数据看作一连串没有边界的字节,然后自己决定分成多大的“包裹”(段 - Segment)来发送。接收方收到的也是一个连续的字节流。
  • 有趣点: 就像水流一样,你往水管里倒水(数据),不用关心一次倒多少,TCP 会保证在另一端流出来的水(数据)是连续不断的(虽然中间可能被分成了很多“水滴”在传输)。
 
 
连接终止 - “合同寄完了,确认下,咱俩都结束啦”
 
  • 原理: 数据传输完毕后,需要优雅地断开连接,确保双方都知道连接已结束。
  • 机制:四次挥手 (Four-Way Handshake)
    • 你: “老王,我这边合同都发完了,准备收摊了哈。” (FIN - 结束请求)
    • 老王: “收到!你等我一下,我看看我这边还有没有数据要发给你,你先别挂电话。” (ACK - 确认收到你的结束请求)
    • (可能老王还有点尾巴数据要发)
    • 老王: “好了,我这边也发完了,我也准备收摊了。” (FIN - 结束请求)
    • 你: “收到!那咱俩都结束了,挂电话吧。” (ACK - 确认收到他的结束请求)
  • 有趣点: 比建立连接多了“一次挥手”,因为可能一方说完了,另一方还有话要说(还有数据要发),需要等双方都确认没东西发了,才能彻底断开。非常严谨!
 
“等待数据发完”的延迟,就是导致挥手需要四次而不是三次的核心原因
 
notion image

1. TIME_WAIT 状态:那个“挂了电话但等一会儿再走”的人
  • 谁会进入? 主动关闭连接的那一方。通常是客户端(因为它通常先请求结束),但也可能是服务器。在四次挥手的第四步,主动方发送了最后一个 ACK 后,它不会立即进入 CLOSED 状态,而是进入 TIME_WAIT 状态。
  • 干嘛的?(存在的意义) 这个状态是 TCP 可靠性的最后一道屏障,主要有两个目的:
      1. 确保对方(被动关闭方)能收到最后的 ACK: 想象一下,如果主动方发送完最后的 ACK (第四次挥手) 后立刻消失 (进入 CLOSED),但这个 ACK 在路上丢了。被动方 (此时在 LAST_ACK 状态) 就收不到这个 ACK,它会超时并重发 FIN (第三次挥手)。但此时主动方已经消失了,这个重发的 FIN 就没人理睬了,被动方可能会一直重发 FIN,或者最终收到一个 RST 报文,导致连接关闭不“优雅”。TIME_WAIT 状态的存在,就是为了让主动方停留足够长的时间 (通常是 2 * MSL),以确保如果最后的 ACK 丢失,它还能收到对方重发的 FIN,并重新发送一次最后的 ACK,帮助对方顺利关闭。
          • MSL (Maximum Segment Lifetime): 报文段最大生存时间。指一个 TCP 报文在网络中能够存活的最长时间。超过这个时间,报文就会被丢弃。2 * MSL 的时间足以保证一个方向的报文及其确认报文都能在网络中消失。
      1. 防止“已失效的连接请求报文段”出现在新连接中: 考虑一种情况:一个连接 (比如 Client A: Port X -> Server B: Port Y) 关闭了。非常快地,一个新的连接又使用了完全相同的四元组 (Client A: Port X -> Server B: Port Y) 建立起来。如果在旧连接关闭时,网络中还有一些“迷路”的、属于旧连接的数据包(因为网络延迟等原因),它们可能会在这个新连接建立后才到达。如果没有 TIME_WAIT 状态,这些旧包就可能被新的连接错误地接收,造成数据混乱。TIME_WAIT 状态持续 2 * MSL 时间,就是为了确保在旧连接关闭后,所有可能残留在网络中的、属于该旧连接的报文段都已自然消失,从而保证新连接不会受到旧连接的干扰。
  • 如果 TIME_WAIT 状态太多会怎么样?
    • 主要问题:占用资源,特别是端口号。 每个 TIME_WAIT 状态的连接虽然不再传输数据,但仍然在内核中占据一个套接字 (socket) 结构,消耗内存资源。更关键的是,它会占用一个本地端口号
    • 后果:端口耗尽。 对于需要频繁、大量、快速建立短连接的场景(比如作为客户端的负载均衡器、爬虫、高并发的 Web 服务器去请求后端服务等),如果每次连接关闭后都要经历一个较长 (几十秒到几分钟) 的 TIME_WAIT 状态,那么可用的临时端口号 (ephemeral port range) 很快就会被用光。一旦端口耗尽,系统就无法发起新的 TCP 连接了,导致业务失败。
    • 怎么办?
      • 系统参数调优(有风险): 比如减小 tcp_tw_reuse (允许将 TIME_WAIT 状态的端口复用于新的出站连接,较安全) 或 tcp_tw_recycle (快速回收 TIME_WAIT 连接,在 NAT 环境下有坑,不推荐开启),或者缩短 TIME_WAIT 的时长 (修改内核参数 tcp_fin_timeout,但通常不建议)。
      • 应用层面优化: 使用长连接 (Keep-Alive) 代替短连接,减少连接建立和关闭的次数。使用连接池。
      • 增加可用端口范围: 修改系统配置 ip_local_port_range。

2. CLOSE_WAIT 状态:那个“收到对方挂电话请求,但自己还没说完话”的人
  • 谁会进入? 被动关闭连接的那一方。通常是服务器。在四次挥手的第二步,被动方收到了主动方的 FIN,并发送了 ACK 后,就进入 CLOSE_WAIT 状态。
  • 干嘛的?(存在的意义) 这个状态表示:“我已经收到了对方(主动关闭方)的关闭请求,并且已经告诉他我知道了 (ACK sent)。但是,我这边可能还有数据要发送,或者我的应用程序还没有准备好关闭这个连接(还没调用 close() 函数)。” TCP 层需要等待本地应用程序调用 close() 方法,然后 TCP 层才会发送自己的 FIN (第三次挥手),并将状态转移到 LAST_ACK。
  • 如果 CLOSE_WAIT 状态太多是为什么?
    • 核心原因:应用程序的锅! 大量连接长时间停留在 CLOSE_WAIT 状态,几乎总是意味着服务器端的应用程序存在问题。具体来说,就是应用程序在收到对方关闭连接的信号后(通常是 read 操作返回 0 或特定错误码),没有及时调用 close() 函数来关闭这个对应的 Socket 连接
    • 可能的原因:
        1. 代码逻辑 Bug: 程序可能在某个分支、循环或异常处理中忘记了调用 close()。
        1. 程序阻塞: 处理该连接的线程可能被阻塞了(比如等待某个锁、等待 I/O、死循环),导致无法执行到 close() 语句。
        1. 资源耗尽: 服务器资源(如线程池满了、内存不足)导致无法及时处理连接关闭的逻辑。
        1. 业务逻辑复杂: 可能业务逻辑设计上,关闭连接前需要完成很多耗时操作,导致 close() 调用延迟。
    • 后果:资源泄露! 和 TIME_WAIT 不同,CLOSE_WAIT 状态会一直持续下去,直到应用程序调用 close() 为止。如果应用程序永远不调用,这个连接就会永远停留在 CLOSE_WAIT 状态。这会导致:
      • 文件描述符耗尽: 每个 CLOSE_WAIT 连接都占用一个文件描述符 (file descriptor)。如果数量过多,会耗尽系统的文件描述符限制,导致无法接受新的连接或打开新的文件。
      • 内存泄露: 每个连接占用的内存资源无法释放。
      • 拖垮服务器: 大量半关闭的连接持续消耗系统资源,最终可能导致服务器响应缓慢甚至宕机。
    • 怎么办?
      • 排查应用程序代码: 仔细检查处理网络连接的代码,确保所有可能的代码路径在连接需要关闭时都正确调用了 close()。
      • 检查线程/进程状态: 使用 jstack (Java)、gdb (C/C++) 等工具检查处理这些连接的线程是否被阻塞或卡死。
      • 监控服务器资源: 检查 CPU、内存、文件描述符使用情况。
      • 代码Review和测试: 加强代码审查和异常情况的测试。

总结对比:
特性
TIME_WAIT
CLOSE_WAIT
谁进入
主动关闭方 (通常是 Client)
被动关闭方 (通常是 Server)
何时进入
发送完第四次挥手的 ACK 后
收到第一次挥手的 FIN 并发出 ACK (第二次挥手) 后
目的
确保最后 ACK 可靠送达;防止旧连接数据干扰新连接
等待本地应用程序处理完数据并调用 close()
持续时间
固定时长 (2*MSL),通常几十秒到几分钟
不定,取决于应用程序何时调用 close(),可能无限长
过多原因
大量短连接、高并发请求 (网络层面/架构层面)
应用程序 Bug / 阻塞 / 资源问题 (应用层面)
主要危害
端口耗尽,无法建立新连接
文件描述符、内存泄露,拖垮服务器
严重性
常见,需关注和调优
严重,通常表明程序有缺陷,需立即修复
 
 
总结一下 TCP 必须掌握的核心:
  • 它是 可靠的:通过 序号、确认应答、超时重传 保证数据不错、不丢、不乱。
  • 它是 面向连接的:通过 三次握手 建立连接,四次挥手 断开连接,保证双方状态同步。
  • 它有 流量控制:通过 滑动窗口 匹配收发双方的处理能力。
  • 它有 拥塞控制:通过 慢启动、拥塞避免 等机制,适应网络状况,防止搞垮整个网络。
  • 它是 面向字节流的:应用层无需关心数据如何分包。
 

3. 网络层 (Internet Layer / Network Layer) - “写清跨省市的详细地址,规划全国路线”

  • 核心任务: 负责将数据包从源主机路由到目标主机,跨越多个不同的网络。核心是寻址路由
  • 通俗解释: 这一层就像是全球邮政系统的核心,负责看懂包裹上的最终地址(IP 地址),并决定这个包裹下一站应该交给哪个中转站(路由器),最终能从你的城市送到朋友所在的城市。
  • 包裹比喻:
    • IP 地址 (Internet Protocol Address): 就像包裹上写的完整的、唯一的收件人街道地址(例如:XX省 XX市 XX区 XX路 XX号)。它标识了你的电脑或朋友的电脑在整个互联网中的逻辑位置。有 IPv4 和 IPv6 两种格式。
    • 路由器 (Router): 就像沿途的邮政分拣中心。每个路由器只看目标 IP 地址,然后根据自己的“地图”(路由表),决定把包裹发往下一个最合适的路由器,一跳一跳地接近目的地。
    • IP 协议本身是“不可靠”的: 它只负责指路,但不保证包裹一定能送到,或者按顺序到达(这个保证由上层 TCP 负责)。
  • 数据单位: 称为 包 (Packet)IP 数据报 (IP Datagram)
 
 

IP

 
如果说 TCP 是那个负责打包、签收、确保合同万无一失的“私人快递管家”,那么 IP 就是整个庞大、覆盖全球的“基础邮政系统”本身,以及在上面奔跑的“邮递车”。
IP 的核心任务只有一个:尽力而为地 (Best-Effort) 把一个“数据包裹”(IP 数据报 - Datagram)从源头地址送到目的地地址。 它只关心“送到哪儿”和“怎么走”,至于包裹本身的安全、顺序、是否一定送到,它不太操心(这些是 TCP 的活儿)。
 
IP 地址 (IP Address) - 全球唯一的“门牌号”
  • 原理: 在互联网这个巨大的网络里,每台想要通信的设备(电脑、手机、服务器等)都需要一个独一无二的地址,这样别人才能找到它,它也知道把回信寄到哪里。
  • 机制:
    • IPv4 地址: 我们最常见的那种,像 192.168.1.100 这样由四个数字组成(每个数字 0-255)。你可以把它想象成“XX小区 XX栋 XX单元 XXX室”。它由 网络部分主机部分 组成。
    • 子网掩码 (Subnet Mask): 像 255.255.255.0 这样的东西,用来帮助设备区分 IP 地址的哪部分是“小区名”(网络部分),哪部分是“门牌号”(主机部分)。这样设备才知道对方是在同一个“小区”(局域网)可以直接送信,还是要交给“邮局总局”(网关/路由器)转发出去。
    • IPv6 地址: 由于 IPv4 地址快用完了(全球门牌号不够了!),推出了 IPv6。它长得多,像 2001:0db8:85a3:0000:0000:8a2e:0370:7334。可以想象成超级详细的地址,确保未来很长时间内地址都够用。原理类似,也是为了唯一标识设备。
    • 公网 IP vs. 私网 IP: 公网 IP 是全球唯一的,就像你在邮局登记的真实家庭住址。私网 IP (比如 192.168.x.x, 10.x.x.x) 是在局部范围内(比如你家里的路由器下、公司内网)使用的,像小区内部的房间号,外面的人不知道,也不能直接寄信到这个内部房间号。需要通过“小区门卫”(NAT 网关)来转换地址才能和外界通信。
 
 
怎么利用子网掩码去查:
 
场景:
假设你的电脑 IP 地址是 192.168.1.100,子网掩码是 255.255.255.0。
现在你想给另一台电脑,IP 地址为 192.168.1.150 的电脑发送一个文件。
你的电脑需要判断: 这台目标电脑 (192.168.1.150) 是不是和我在同一个小区(同一个局域网)
  • 如果是: 太好了!我直接把文件“扔”过去就行了(通过局域网内部的交换机直接发送)。
  • 如果不是: 那我得把文件交给“小区门卫”(也就是网关/路由器),让门卫帮忙转寄出去。
子网掩码如何帮助判断? - “遮盖”大法
子网掩码的作用就像一个“遮罩”或者“滤镜”。它和 IP 地址进行一种特殊的数学运算(按位与 - Bitwise AND),运算结果就能得到这个 IP 地址所在的“小区名”(网络地址)。
为了看清楚这个运算,我们得把 IP 地址和子网掩码都转换成 二进制 (电脑实际处理的方式):
  • 你的 IP: 192.168.1.100
    • 二进制: 11000000.10101000.00000001.01100100
  • 子网掩码: 255.255.255.0
    • 二进制: 11111111.11111111.11111111.00000000
按位与 (AND) 运算规则: 只有当两个位都是 1 时,结果才是 1;否则结果是 0。
现在,我们把你的 IP 地址和子网掩码进行按位与运算:
11000000.10101000.00000001.01100100 (你的 IP: 192.168.1.100) & 11111111.11111111.11111111.00000000 (子网掩码: 255.255.255.0) ------------------------------------ 11000000.10101000.00000001.00000000 (运算结果)
运算结果 的二进制是 11000000.10101000.00000001.00000000。
转换回十进制,就是 192.168.1.0。
这个 192.168.1.0 就是你所在网络的 网络地址,也就是你的“小区名”。
关键看子网掩码的 0:
你会发现,子网掩码是 1 的部分,对应的 IP 地址位被保留下来了(因为 X AND 1 = X);而子网掩码是 0 的部分,对应的 IP 地址位都被变成了 0(因为 X AND 0 = 0)。
所以 255.255.255.0 这个掩码的意思就是:“前三个数字 (192.168.1) 是网络部分(小区名),最后一个数字 (100) 是主机部分(门牌号)。”
现在判断目标电脑 192.168.1.150:
你的电脑会对目标 IP 地址也执行同样的操作:
  • 目标 IP: 192.168.1.150
    • 二进制: 11000000.10101000.00000001.10010110
  • 你的子网掩码: 255.255.255.0
    • 二进制: 11111111.11111111.11111111.00000000
进行按位与运算:
11000000.10101000.00000001.10010110 (目标 IP: 192.168.1.150) & 11111111.11111111.11111111.00000000 (你的子网掩码: 255.255.255.0) ------------------------------------ 11000000.10101000.00000001.00000000 (运算结果)
 
 
运算结果的二进制转换回十进制,还是 192.168.1.0。
对比结果:
  • 你的网络地址(小区名)是 192.168.1.0。
  • 目标电脑的网络地址(小区名)也是 192.168.1.0。
结论: 两个网络地址相同!你的电脑判断出:“哦!这台 192.168.1.150 的电脑就在我们同一个小区!” 于是,它就会直接在局域网内发送数据包,而不需要通过网关。
再来个反例:
如果你想访问 8.8.8.8 (Google 的一个 DNS 服务器)。
  • 目标 IP: 8.8.8.8
    • 二进制: 00001000.00001000.00001000.00001000
  • 你的子网掩码: 255.255.255.0
    • 二进制: 11111111.11111111.11111111.00000000
按位与运算:
00001000.00001000.00001000.00001000 (目标 IP: 8.8.8.8) & 11111111.11111111.11111111.00000000 (你的子网掩码: 255.255.255.0) ------------------------------------ 00001000.00001000.00001000.00000000 (运算结果)
运算结果是 8.8.8.0。
对比结果:
  • 你的网络地址是 192.168.1.0。
  • 目标 8.8.8.8 的网络地址是 8.8.8.0。
结论: 两个网络地址不相同!你的电脑判断出:“这家伙不在我们小区!” 于是,它就会把数据包发送给你配置的默认网关 (Default Gateway),让网关(路由器)负责把这个包转发到外面的互联网上去。
总结:
子网掩码就像一把“尺子”,通过和 IP 地址进行按位与运算,就能精确地“量”出这个 IP 地址的网络部分(小区名)。计算机通过比较自己所在网络的“小区名”和目标 IP 地址的“小区名”是否一致,来决定数据包是直接在本地发送,还是交给网关转发。
 
 
 
IP 数据报 (IP Datagram) / 包 (Packet) - 标准化的“快递包裹”
  • 原理: 要寄送的数据(比如 TCP 发来的合同片段)不能直接扔到网络上,需要按照 IP 协议规定的格式打包。
  • 机制:
    • IP 头部 (Header): 包裹的“快递面单”。上面写着最重要的信息:
      • 源 IP 地址: 发件人地址。
      • 目标 IP 地址: 收件人地址。
      • TTL (Time-To-Live): 生存时间。下面会讲。
      • 协议号: 表明包裹里面装的是什么类型的数据(比如 告诉上一层,这是个 TCP 包裹,请交给 TCP 处理)。
      • 其他信息:版本号 (IPv4/IPv6)、头部校验和(检查面单有没有损坏)等。
    • 数据负载 (Payload): 包裹里实际装的东西,比如 TCP 段、UDP 数据报等。
 
 
 
 
 
 
路由 (Routing) - “问路”与“指路”的过程
  • 原理: 互联网是由无数个子网络和路由器连接而成的。一个包裹从源头到目的地,通常需要经过很多个“中转站”(路由器)。路由就是决定包裹下一跳应该去往哪个中转站的过程。
  • 机制:
    • 路由器 (Router): 网络世界的“十字路口”或“邮政分拣中心”。它连接着不同的网络。
    • 路由表 (Routing Table): 每个路由器心里都有一本“地图”或“通讯录”(路由表)。这个表告诉路由器:“要去某个目标网络(比如 XX 小区),下一站应该交给隔壁的 Y 路由器处理。”
    • 逐跳转发 (Hop-by-Hop Forwarding): 包裹到达一个路由器后,路由器查看包裹的目标 IP 地址,在自己的路由表里查找匹配的条目,找到下一跳的地址,然后把包裹转发给那个下一跳路由器。它不关心全程路线,只关心“下一步交给谁”。就像问路,你问去天安门怎么走,路人告诉你“先往前走到下个路口左转”,他不会告诉你全程路线。
    • 路由协议 (Routing Protocols): 比如 OSPF, BGP 等。路由器之间通过这些协议互相“交流信息”、“更新地图”,动态地学习网络拓扑结构,建立和维护路由表。就像邮局之间互通有无,更新彼此负责的派送范围和最佳路线。
 
 
 
尽力而为 (Best-Effort Delivery) - “我只管送,丢了、乱了、慢了别找我”
  • 原理: 这是 IP 协议的核心设计哲学。为了保持简单、高效和灵活,IP 协议本身不提供任何可靠性保证。
  • 机制体现:
    • 不保证送达: 包裹在传输过程中可能因为网络拥堵、路由器故障、TTL 耗尽等原因丢失。IP 不负责重传。
    • 不保证按序: 由于路由路径可能不同,先发出的包裹可能后到。IP 不负责排序。
    • 不保证不重复: 极少数情况下可能收到重复的包裹。IP 不负责去重。
    • 无连接 (Connectionless): 发送前不需要像 TCP 那样先“打电话”建立连接。每个数据包都是独立发送的。
 
 
TTL (Time-To-Live) - 包裹的“保质期”或“最大中转次数”
  • 原理: 防止数据包因为路由配置错误等原因在网络中无限循环,最终耗尽网络资源。
  • 机制: IP 头部有一个 TTL 字段(通常是一个数字,比如 64 或 128)。每经过一个路由器,路由器就把这个 TTL 值减 1。如果 TTL 减到 0 了,路由器就会丢弃这个数据包,并通常会向源头发一个 ICMP “超时”消息(告诉发件人:你的包裹超时了)。
  • 有趣点: 就像给每个包裹设定了一个“最多能经过多少个邮局”的限制,防止它迷路后永远在邮政系统里打转。traceroute (或 tracert) 命令就是利用这个机制来探测数据包到达目的地所经过的路径的。
 
 
 
  • IP 地址: 网络设备的唯一标识,是寻址的基础 (包括 IPv4/IPv6, 公网/私网, 子网掩码)。
  • IP 数据报: 标准化的数据封装格式,包含源/目的地址等关键信息。
  • 路由: 基于路由表的逐跳转发机制,决定数据包的传输路径。
  • 尽力而为: 不保证可靠性、顺序性,是 IP 的核心特点 (快但不靠谱)。
  • TTL: 防止数据包在网络中无限循环的机制。
 
 

4. 网络接口层 (Network Interface Layer / Link Layer) - “最后一公里的快递员和交通工具”

  • 核心任务: 处理在**同一个物理网络(局域网)**内部的数据传输,将 IP 数据包封装成帧,并处理物理硬件地址(MAC 地址)和具体的物理传输介质。
  • 通俗解释: 这是最底层,负责实际的“跑腿”工作。当包裹到达你朋友所在城市的最后一个邮局(路由器)后,这一层负责把它准确送到朋友家的具体门牌号。它也规定了是用卡车、摩托车还是自行车(对应网线、Wi-Fi 等)来送。
  • 包裹比喻:
    • MAC 地址 (Media Access Control Address): 像是身份证号或者设备网卡的唯一序列号,或者你家在小区里的具体门牌号。它只在同一个局域网内(比如你家里的所有设备连到同一个路由器)才有效,用来标识网络中的具体设备。当路由器要把包裹交给最终的电脑时,它需要知道这台电脑的 MAC 地址。
    • 物理传输: 把数字信息(0和1)转换成电信号(通过网线)、光信号(通过光纤)或无线电波(通过 Wi-Fi),在物理链路上发送出去。
    • 协议举例: 以太网 (Ethernet) 协议(用于有线连接)、Wi-Fi (IEEE 802.11) 协议(用于无线连接)。
  • 数据单位: 称为 帧 (Frame)
 
 
 
docker操作系统
Loading...
Catalog