图解计算机网络

发布于:2025-07-31 ⋅ 阅读:(22) ⋅ 点赞:(0)

一、基础篇

1.1 TCP/IP 四层网络模型

应用层

最上层的,也是我们能直接接触到的就是应用层(Application Layer),我们电脑或手机使用的应用软件都是在应用层实现。那么,当两个不同设备的应用需要通信的时候,应用就把应用数据传给下一层,也就是传输层。 所以,应用层只需要专注于为用户提供应用功能,比如 HTTP、FTP、Telnet、DNS、SMTP等。 应用层是不用去关心数据是如何传输的,就类似于,我们寄快递的时候,只需要把包裹交给快递员,由他负责运输快递,我们不需要关心快递是如何被运输的。 而且应用层是工作在操作系统中的用户态,传输层及以下则工作在内核态。

传输层

应用层的数据包会传给传输层,传输层Transport Layer)是为应用层提供网络支持的。

在传输层会有两个传输协议,分别是 TCP 和 UDP。 TCP 的全称叫传输控制协议(Transmission Control Protocol),⼤部分应⽤使⽤的正是 TCP 传输层协 议,⽐如 HTTP 应⽤层协议。 TCP 相⽐ UDP 多了很多特性,⽐如流量控制、超时重传、拥塞控制 等,这些都是为了保证数据包能可靠地传输给对⽅。 UDP 相对来说就很简单,简单到只负责发送数据包,不保证数据包是否能抵达对⽅,但它实时性相 对更好,传输效率也⾼。 当然,UDP 也可以实现可靠传输,把 TCP 的特性在应⽤层上实现就可以, 不过要实现⼀个商⽤的可靠 UDP 传输协议,也不是⼀件简单的事情。 应⽤需要传输的数据可能会⾮常⼤,如果直接传输就不好控制,因此当传输层的数据包⼤⼩超过 MSS(TCP 最⼤报⽂段⻓度) ,就要将数据包分块,这样即使中途有⼀个分块丢失或损坏了,只需 要重新发送这⼀个分块,⽽不⽤重新发送整个数据包。 在 TCP 协议中,我们把每个分块称为⼀ 个 TCP 段(TCP Segment)。

当设备作为接收方时,传输层则要负责把数据包传给应用,但是一台设备上可能会有很多应用在接收或者传输数据,因此需要用一个编号将应用区分开来,这个编号就是端口。 比如 80 端口通常是 Web 服务器用的,22 端口通常是远程登录服务器用的。而对于浏览器(客户端)中的每个标签栏都是一个独立的进程,操作系统会为这些进程分配临时的端口号。 由于传输层的报文中会携带端口号,因此接收方可以识别出该报文是发送给哪个应用。

网络层

传输层可能大家刚接触的时候,会认为它负责将数据从一个设备传输到另一个设备,事实上它并不负责。

实际场景中的网络环节是错综复杂的,中间有各种各样的线路和分叉路口,如果一个设备的数据要传输给另一个设备,就需要在各种各样的路径和节点进行选择,而传输层的设计理念是简单、高效、专注,如果传输层还负责这一块功能就有点违背设计原则了。

也就是说,我们不希望传输层协议处理太多的事情,只需要服务好应用即可,让其作为应用间数据传输的媒介,帮助实现应用到应用的通信,而实际的传输功能就交给下一层,也就是网络层(Internet Layer)。

网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。

网络层负责将数据从一个设备传输到另一个设备,世界上那么多设备,又该如何找到对方呢?因此,网络层需要有区分设备的编号。 我们一般用 IP 地址给设备进行编号,对于 IPv4 协议, IP 地址共 32 位,分成了四段(比如,192.168.100.1),每段是 8 位。只有一个单纯的 IP 地址虽然做到了区分设备,但是寻址起来就特别麻烦,全世界那么多台设备,难道一个一个去匹配?这显然不科学。 因此,需要将 IP 地址分成两种意义:

• 一个是网络号,负责标识该 IP 地址是属于哪个「子网」的;

• 一个是主机号,负责标识同一「子网」下的不同主机;

怎么分的呢?这需要配合子网掩码才能算出 IP 地址 的网络号和主机号。

举个例子,比如 10.100.122.0/24,后面的/24表示就是 255.255.255.0 子网掩码,255.255.255.0 二进制是「11111111-11111111-11111111-00000000」,大家数数一共多少个1?不用数了,是 24 个1,为了简化子网掩码的表示,用/24代替255.255.255.0。

知道了子网掩码,该怎么计算出网络地址和主机地址呢?

将 10.100.122.2 和 255.255.255.0 进行按位与运算,就可以得到网络号,如下图:

将 255.255.255.0 取反后与IP地址进行进行按位与运算,就可以得到主机号。

大家可以去搜索下子网掩码计算器,自己改变下「掩码位」的数值,就能体会到子网掩码的作用了。

那么在寻址的过程中,先匹配到相同的网络号(表示要找到同一个子网),才会去找对应的主机。

除了寻址能力, IP 协议还有另一个重要的能力就是路由。实际场景中,两台设备并不是用一条网线连接起来的,而是通过很多网关、路由器、交换机等众多网络设备连接起来的,那么就会形成很多条网络的路径,因此当数据包到达一个网络节点,就需要通过路由算法决定下一步走哪条路径。

路由器寻址工作中,就是要找到目标地址的子网,找到后进而把数据包转发给对应的网络内。

所以,IP 协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘。

网络接口层

所以,IP 协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘。

IP 头部中的接收方 IP 地址表示网络包的目的地,通过这个地址我们就可以判断要将包发到哪里,但在以太网的世界中,这个思路是行不通的。

什么是以太网呢?电脑上的以太网接口,Wi-Fi接口,以太网交换机、路由器上的千兆,万兆以太网口,还有网线,它们都是以太网的组成部分。以太网就是一种在「局域网」内,把附近的设备连接起来,使它们之间可以进行通讯的技术。

以太网在判断网络包目的地时和 IP 的方式不同,因此必须采用相匹配的方式才能在以太网中将包发往目的地,而 MAC 头部就是干这个用的,所以,在以太网进行通讯要用到 MAC 地址。

MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息,我们可以通过 ARP 协议获取对方的 MAC 地址。

所以说,网络接口层主要为网络层提供「链路级别」传输的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。

网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。

1.2 输入网址到显示页面,期间发生了什么?

URL解析

首先浏览器做的第一步工作就是要对 URL 进行解析,从而生成发送给 Web 服务器的请求信息。

对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。

域名解析

通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web 服务器。 但在发送之前,还有一项工作需要完成,那就是查询服务器域名对应的 IP 地址,因为委托操作系统发送消息时,必须提供通信对象的 IP 地址。

比如我们打电话的时候,必须要知道对方的电话号码,但由于电话号码难以记忆,所以通常我们会将对方电话号 + 姓名保存在通讯录里。

所以,有一种服务器就专门保存了 Web 服务器域名与 IP 的对应关系,它就是 DNS 服务器。

域名解析的流程:

1.客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。

2. 本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。

3. 根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。”

4. 本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server.com 的 IP 地址吗?”

5. 顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。

6. 本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。

7. 权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。

8. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

可靠传输——TCP

HTTP 是基于 TCP 协议传输的,所以在这我们先了解下 TCP 协议。

报文头部格式:

首先,源端口号和目标端口号是不可少的,如果没有这两个端口号,数据就不知道应该发给哪个应用。

接下来有包的序号,这个是为了解决包乱序的问题。 还有应该有的是确认号,目的是确认发出去对方是否有收到。如果没有收到就应该重新发送,直到送达,这个是为了解决丢包的问题。

接下来还有一些状态位。例如 SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束连接等。TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。

还有一个重要的就是窗口大小。TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力,别发送的太快,撑死我,也别发的太慢,饿死我。

除了做流量控制以外,TCP还会做拥塞控制,对于真正的通路堵车不堵车,它无能为力,唯一能做的就是控制自己,也即控制发送的速度。不能改变世界,就改变自己嘛。

在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手。

一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。

• 然后客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。

• 服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。

• 客户端收到服务端发送的 SYN 和 ACK 之后,发送对 SYN 确认的 ACK,之后处于 ESTABLISHED状态,因为它一发一收成功了。

• 服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。 所以三次握手目的是保证双方都有发送和接收的能力。

TCP 的连接状态查看,在 Linux 可以通过 netstat -napt 命令查看。

如果 HTTP 请求消息⽐较⻓,超过了 MSS 的⻓度,这时 TCP 就需要把 HTTP 的数据拆解成⼀块块的 数据发送,⽽不是⼀次性发送所有数据。

  • MTU :⼀个⽹络包的最⼤⻓度,以太⽹中⼀般为 1500 字节。
  • MSS :除去 IP 和 TCP 头部之后,⼀个⽹络包所能容纳的 TCP 数据的最⼤⻓度。

数据会被以 MSS 的⻓度为单位进⾏拆分,拆分出来的每⼀块数据都会被放进单独的⽹络包中。也 就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据。

TCP 协议⾥⾯会有两个端⼝,⼀个是浏览器监听的端⼝(通常是随机⽣成的),⼀个是 Web 服务器 监听的端⼝(HTTP 默认端⼝号是 80 , HTTPS 默认端⼝号是 443 )。

在双⽅建⽴了连接后,TCP 报⽂中的数据部分就是存放 HTTP 头部 + 数据,组装好 TCP 报⽂之后, 就需交给下⾯的⽹络层处理。

⾄此,⽹络包的报⽂如下图:

远程定位——IP

TCP 模块在执⾏连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成⽹络包发送给 通信对象。

IP报文头部格式:

在 IP 协议⾥⾯需要有源地址 IP 和 ⽬标地址 IP: 源地址IP,即是客⼾端输出的 IP 地址; ⽬标地址,即通过 DNS 域名解析得到的 Web 服务器 IP。 因为 HTTP 是经过 TCP 传输的,所以在 IP 包头的协议号,要填写为 06 (⼗六进制),表⽰协议为 TCP。

网络包报文:

两点传输——MAC

生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部。

MAC 头部是以太⽹使⽤的头部,它包含了接收⽅和发送⽅的 MAC 地址等信息。

在 MAC 包头⾥需要发送⽅ MAC 地址和接收⽅⽬标 MAC 地址,⽤于两点之间的传输。 ⼀般在 TCP/IP 通信⾥,MAC 包头的协议类型只使⽤:

0800 : IP 协议

0806 : ARP 协议

MAC发送方和接收方如何确认?

发送⽅的 MAC 地址获取就⽐较简单了,MAC 地址是在⽹卡⽣产时写⼊到 ROM ⾥的,只要将这个值 读取出来写⼊到 MAC 头部就可以了。

接收⽅的 MAC 地址就有点复杂了,只要告诉以太⽹对⽅的 MAC 的地址,以太⽹就会帮我们把包发 送过去,那么很显然这⾥应该填写对⽅的 MAC 地址。

所以先得搞清楚应该把包发给谁,这个只要查⼀下路由表就知道了。在路由表中找到相匹配的条 ⽬,然后把包发给 Gateway 列中的 IP 地址就可以了。

出口——网卡

⽹络包只是存放在内存中的⼀串⼆进制数字信息,没有办法直接发送给对⽅。因此,我们需要将数 字信息转换为电信号,才能在⽹线上传输,也就是说,这才是真正的数据发送过程。 负责执⾏这⼀操作的是⽹卡,要控制⽹卡还需要靠⽹卡驱动程序。 ⽹卡驱动获取⽹络包之后,会将其复制到⽹卡内的缓存区中,接着会在其开头加上报头和起始帧分 界符,在末尾加上⽤于检测错误的帧校验序列。

送别者——交换机

二、HTTP篇

2.1 GET和POST的区别

GET 的语义是从服务器获取指定的资源,这个资源可以是静态的⽂本、⻚⾯、图⽚视频等。GET 请 求的参数位置⼀般是写在 URL 中,URL 规定只能⽀持 ASCII,所以 GET 请求的参数只允许 ASCII 字 符 ,⽽且浏览器会对 URL 的⻓度有限制(HTTP协议本⾝对 URL⻓度并没有做任何规定)。

POST 的语义是根据请求负荷(报⽂body)对指定的资源做出处理,具体的处理⽅ 式视资源类型⽽不同。POST 请求携带数据的位置⼀般是写在报⽂ body 中,body 中的数据可以是 任意格式的数据,只要客⼾端与服务端协商好即可,⽽且浏览器不会对 body ⼤⼩做限制。

GET 和 POST ⽅法都是安全和幂等的吗?

先说明下安全和幂等的概念:

在 HTTP 协议⾥,所谓的「安全」是指请求⽅法不会「破坏」服务器上的资源。

所谓的「幂等」,意思是多次执⾏相同的操作,结果都是「相同」的。

如果从 RFC 规范定义的语义来看: GET ⽅法就是安全且幂等的,因为它是「只读」操作,⽆论操作多少次,服务器上的数据都是安 全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览 器本⾝上(彻底避免浏览器发请求),也可以做到代理上(如nginx),⽽且在浏览器中 GET 请求 可以保存为书签。

POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交 数据就会创建多个资源,所以不是幂等的。所以,浏览器⼀般不会缓存 POST 请求,也不能把 POST 请求保存为书签。

做个简要的⼩结。 GET 的语义是请求获取指定的资源。GET ⽅法是安全、幂等、可被缓存的。 POST 的语义是根据请求负荷(报⽂主体)对指定的资源做出处理,具体的处理⽅式视资源类型⽽不 同。POST 不安全,不幂等,(⼤部分实现)不可缓存。 注意, 上⾯是从 RFC 规范定义的语义来分析的。 但是实际过程中,开发者不⼀定会按照 RFC 规范定义的语义来实现 GET 和 POST ⽅法。⽐如: 可以⽤ GET ⽅法实现新增或删除数据的请求,这样实现的 GET ⽅法⾃然就不是安全和幂等。 可以⽤ POST ⽅法实现查询数据的请求,这样实现的 POST ⽅法⾃然就是安全和幂等。

曾经有个笑话,有⼈写了个博客,删除博客⽤的是 GET 请求,他觉得没⼈访问就连鉴权都没做。然 后 Google 服务器爬⾍爬了⼀遍,他所有博⽂就没了。。。 如果「安全」放⼊概念是指信息是否会被泄漏的话,虽然 POST ⽤ body 传输数据,⽽ GET ⽤ URL 传输,这样数据会在浏览器地址拦容易看到,但是并不能说 GET 不如 POST 安全的。 因为 HTTP 传输的内容都是明⽂的,虽然在浏览器地址拦看不到 POST 提交的 body 数据,但是只要 抓个包就都能看到了。 所以,要避免传输过程中数据被窃取,就要使⽤ HTTPS 协议,这样所有 HTTP 的数据都会被加密传输。

2.2 HTTP/1.1 的优点有哪些?

HTTP最突出的优点是「简单、灵活和易于扩展、应⽤⼴泛和跨平台」。

1. 简单 HTTP 基本的报⽂格式就是 header + body ,头部信息也是 key-value 简单⽂本的形式,易于理 解,降低了学习和使⽤的⻔槛。

2. 灵活和易于扩展 HTTP 协议⾥的各类请求⽅法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许 开发⼈员⾃定义和扩充。 同时 HTTP 由于是⼯作在应⽤层( OSI 第七层),则它下层可以随意变化,⽐如: HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层; HTTP/1.1 和 HTTP/2.0 传输协议使⽤的是 TCP 协议,⽽到了 HTTP/3.0 传输协议改⽤了 UDP 协 议。

3. 应⽤⼴泛和跨平台 互联⽹发展⾄今,HTTP 的应⽤范围⾮常的⼴泛,从台式机的浏览器到⼿机上的各种 APP,从看新 闻、刷贴吧到购物、理财、吃鸡,HTTP 的应⽤遍地开花,同时天然具有跨平台的优越性。

2.3 HTTP/1.1 的缺点有哪些?

HTTP 协议⾥有优缺点⼀体的双刃剑,分别是「⽆状态、明⽂传输」,同时还有⼀⼤缺点「不安全」。

1. ⽆状态双刃剑。

⽆状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的 CPU 和内存⽤来对外提供服务。

⽆状态的坏处,既然服务器没有记忆能⼒,它在完成有关联性的操作时会⾮常⿇烦。 例如登录->添加购物⻋->下单->结算->⽀付,这系列操作都要知道⽤⼾的⾝份才⾏。但服务器不知 道这些请求是有关联的,每次都要问⼀遍⾝份信息。 这样每操作⼀次,都要验证信息,这样的购物体验还能愉快吗?别问,问就是酸爽!

对于⽆状态的问题,解法⽅案有很多种,其中⽐较简单的⽅式⽤ Cookie 技术。 Cookie 通过在请求和响应报⽂中写⼊ Cookie 信息来控制客⼾端的状态。 相当于,在客⼾端第⼀次请求后,服务器会下发⼀个装有客⼾信息的「⼩贴纸」,后续客⼾端请求服 务器的时候,带上「⼩贴纸」,服务器就能认得了了。

2. 明⽂传输双刃剑

明⽂意味着在传输过程中的信息,是可⽅便阅读的,⽐如 Wireshark 抓包都可以直接⾁眼查看,为我 们调试⼯作带了极⼤的便利性。 但是这正是这样,HTTP 的所有信息都暴露在了光天化⽇下,相当于信息裸奔。在传输的漫⻓的过程 中,信息的内容都毫⽆隐私可⾔,很容易就能被窃取,如果⾥⾯有你的账号密码信息,那你号没了。

3.HTTP ⽐较严重的缺点就是不安全: 通信使⽤明⽂(不加密),内容可能会被窃听。

⽐如,账号信息容易泄漏,那你号没了。 不验证通信⽅的⾝份,因此有可能遭遇伪装。⽐如,访问假的淘宝、拼多多,那你钱没了。 ⽆法证明报⽂的完整性,所以有可能已遭篡改。⽐如,⽹⻚上植⼊垃圾⼴告,视觉污染,眼没 了。 HTTP 的安全问题,可以⽤ HTTPS 的⽅式解决,也就是通过引⼊ SSL/TLS 层,使得在安全上达到了 极致。


网站公告

今日签到

点亮在社区的每一天
去签到