计算机网络原理
TCP 和 UDP 协议
HTTP 协议在 OSI 模型的哪一层?
HTTP协议在OSI模型中属于应用层协议。HTTP(超文本传输协议)是用于在Web上进行数据传输的协议,主要负责客户端和服务器之间的通信。
HTTP协议定义了请求和响应的格式,以及如何传输数据,因此它位于OSI模型的最高层——应用层。
OSI模型的七层
物理层
数据链路层
网络层
传输层
会话层
表示层
应用层
TCP/IP五层模型
应用层
传输层
网络层
数据链路层
物理层
TCP 协议三次握手、四次挥手详解(必会)
三次握手,以客户端向服务端发起TCP链接请求举例子。
(有条件建议画图说明)
客户端在主动打开链接后,发起 第一次握手(SYN=1,seq=x)。
服务端在收到第一次握手报文段后,发送 第二次握手(SYN=1,ACK=1,seq=y,ack=x+1)。此时能够证明,服务端可以正确收到客户端发来的信息,并向客户端继续索要编号为x+1的报文段。
客户端在收到第二次握手报文段后,会发送 第三次握手(ACK=1,seq=x+1,ack=y+1)。此时能够证明,客户端能够正确收到服务端发来的消息。
第三次握手信息到达服务端后,TCP链接建立,握手过程结束。此时服务端知道客户端能够收到自己的信息。
四次挥手,以客户端做为主动断开链接的一方举例。

客户端在报文发送结束后,希望进入终止程序,所以进行 第一次挥手(FIN=1,seq=u)。这条信息告知服务端,客户端已经发完信息,希望断联。
服务端在收到第一次挥手的报文段后,没有立即进入终止程序,因为可能还存在没有发送完的信息,所以进行 第二次挥手(ACK=1,seq=v,ack=u+1)。这条报文段是为了告知客户端,你(C)希望断开的信息我(S)收到了。
此时进入半关状态,服务端在一段时间之后,数据也发送完毕,则进入终止程序,主动进行 第三次挥手(FIN=1,seq=w,ACK=1,ack=u+1)。这条报文段告知客户端,我的信息已发完,可以断联。
客户端在收到第三次挥手的报文段后,进行 第四次挥手(ACK=1,seq=u+1,ack=w+1)。这条报文段告知服务端,你(S)希望断开的信息我(C)收到了。
为什么 TCP 协议握手是三次,而挥手需要四次
可以回答为:因为服务端不一定马上能关闭。。
因为在断开TCP链接挥手阶段的时候,被动断开的一方可能还有信息没有发送完,所以产生了收到 FIN 终止报文后的回复报文 和 终止报文两个报文,相比握手要多一个挥手次数。
TCP 和 UDP 的原理、区别、使用场景
原理:
TCP 协议通过三次握手建立连接,四次挥手断开连接,提供可靠的数据传输服务。TCP 协议还在 IP 协议上实现了校验、序号机制、确认和重传机制。保证了数据传输的安全性和可靠性。
UDP 协议仅仅在 IP 协议上加入了复用、分用、差错检测。约等于裸奔。
区别、使用场景:
TCP和UDP都是基于网络层IP协议之上的传输层协议,TCP是面向连接的协议,而UDP是无连接的协议。
TCP(Transmission Control Protocol)提供可靠的数据传输服务,确保数据包按顺序到达,并且在传输过程中进行错误检测和纠正。TCP适用于需要保证数据完整性和可靠性的应用,如HTTP、FTP、SMTP等。
UDP(User Datagram Protocol)提供无连接的数据传输服务,不保证数据包的顺序到达,不可靠。UDP适用于小型数据包或对速度要求较高,但对数据完整性不敏感的应用,如视频流、在线游戏、DNS解析等。
TCP的慢启动和拥塞避免
为了防止网络中被注入过多的数据造成网络拥堵,在TCP的拥塞避免算法中使用了:慢启动,拥塞避免,快重传,快恢复等方法。
慢启动:发送端最开始只发送一个报文段,每收到一个回复报文就将可发送数增加 1。所以一个传输轮次中是以二的倍数增加的。
拥塞避免:当发送端的可发送数达到一个阈值时,进入拥塞避免阶段,此时每收到一个回复报文就将可发送数增加 1。
一旦发送端察觉到出现拥堵,就会将发送窗口重新降为1,再次进入慢启动状态。这是为了让网络有时间处理完积压的数据。
快重传:当发送端连续收到三个重复的 ACK 冗余报文时,立即重传丢失的数据包,而不必等待重传定时器到期。
快恢复:当发送端收到三个重复的 ACK 冗余报文时,进入快恢复,发送窗口减小为一半,并进入拥塞避免算法。这是因为,既然能顺利收到3个重复的ACK报文说明非目标报文的后续报文段陆续抵达,此时可以认为网路不存在严重拥堵,不需要退避到1重新进行慢开始。
TCP为什么在关闭链接之后,主动发起关闭的那一方需要等待 2MSL
为什么在TCP断开链接之后,主动断开链接的一方会等待2MSL的时间?
首先,MSL是一个报文段在网络中的最长持续时间,TCP必须等待 2MSL 时长才能彻底断开链接是为了两点:
预留重传时间窗口:如果最后一次挥手的报文段丢失,那么服务器端超时会请求重传,如果提前关闭,服务器端可能无法正确关闭TCP链接。
防止脏数据污染:我们在建立tcp链接的时候是依靠着服务器和客户端的套接字来确认的,也就意味着,如果网络里还有一些延迟的旧数据包没消失,贸然在这个时间建立了新的TCP链接,可能会导致新链接误以为旧包是新数据。
TCP 报文段的首部的标志位有哪些?TIME_WAIT, CLOSE_WAIT 状态各属于哪一方?
TCP 报文段的首部包含以下标志位:
SYN(同步):用于建立连接的标志位。
ACK(确认):用于确认收到数据的标志位。
FIN(结束):用于终止连接的标志位。
RST(重置):用于重置连接的标志位。
PSH(推送):用于提示接收方立即将数据推送给应用层,不用等缓存区满了之后再向上交付。(尽快交付)
URG(紧急):用于标识报文段中有紧急数据的标志位。(尽快发送)
TIME_WAIT:属于主动断联方,当一方主动关闭连接后,会进入 TIME_WAIT 状态,等待 2MSL 的时间,以确保对方收到最后的 ACK 报文段,并且防止旧的报文段干扰新的连接。
CLOSE_WAIT:属于被断联方,当一方被动关闭连接后,但仍有数据需要发送(不发也有这个状态),会进入 CLOSE_WAIT 状态。
粘包拆包是什么,发生在哪一层
粘包和拆包是指在 TCP 协议中,由于 TCP 是一个面向字节流的协议,数据包可能会被分割成多个部分发送(拆包),或者多个数据包可能会被合并成一个数据包发送(粘包)。这主要发生在传输层。
黏包怎么解决?
解决粘包问题的方法有以下几种:
定长消息:每个消息固定长度,接收端按照固定长度读取
分隔符:在消息之间使用特殊的分隔符,接收端根据分隔符进行拆包
消息头:在消息前面添加一个固定长度的消息头,包含消息的长度信息,接收端先读取消息头,然后根据长度信息读取消息体
使用更高级的协议:如HTTP、WebSocket等,这些协议已经内置了解决粘包问题的机制。
SYN + ACK 包能不能拆开来发
SYN + ACK 包不能拆开来发,因为它们是TCP三次握手过程中第二步的一个整体,必须同时发送以确保连接的正确建立。
SYN 同步报文段本身也不携带任何数据。第二次握手的时候之所以要给同步报文段的确认位(ACK)置 1 是因为这也是针对第一次报文的确认报文。
讲讲听说过哪些快速重传算法
快速重传算法是TCP协议中的一种机制,用于在数据包丢失时快速恢复连接。它通过监测连续收到的重复ACK报文段来判断数据包是否丢失。当发送端连续收到三个重复的ACK报文段时,立即重传丢失的数据包,而不必等待重传定时器到期。
上文也提到了,只要接收端漏接了某个报文号,又接到之后的报文号,接收端会返回“冗余ACK”,次数到三次就立刻触发重传。
应用层协议
HTTPS用到的是对称加密还是非对称加密?分别体现在哪里?
HTTPS 即用到了对称加密,也用到了非对称加密。
非对称加密的特点是安全,但是慢。
对称加密的特点是快,但是不安全。
由此,结合 TCP 的特性,我们就可以在握手过程中使用 TLS 协议中的 RSA 算法进行非对称加密。在握手的过程中,浏览器先核实路由器中保存的CA机构签发的证书,并提取公钥。
再之后客户端本地生成一段随机码(密钥),使用公钥进行加密,由于解码这段信息的私钥仅保存在服务器上,所以就算中途被劫持也无法破译,使得密钥的安全性得到保障。
在后续的通信过程中,客户端和服务器就可以使用对称加密算法(如AES)来加密数据,因为双方都已经拥有了相同的密钥,这样可以保证通信的效率。
http协议各个版本
HTTP 1.0
HTTP1.0 协议是每个请求都得重新建立一次TCP链接,结束就会断开,那么一个页面如果有十几个资源,就会导致十几次的TCP链接的建立。性能灾难。关键性能卡点:每个请求都需要重新建立一次TCP链接。
HTTP 1.1
HTTP1.1 协议引入了持久连接(Persistent Connection)和管道化(Pipelining)机制,允许在一个TCP连接上发送多个HTTP请求和响应,从而减少了TCP连接的建立和关闭次数,提高了性能。
关键性能卡点:多个请求发送后,必须按序处理先来后到,才能处理处理下一个请求,这就会产生阻塞时间。这就是所谓的:队头阻塞(Head-of-Line Blocking)问题。
HTTP 2.0
HTTP2.0 协议引入了多路复用(Multiplexing)机制,允许在一个TCP连接上同时发送多个HTTP请求和响应,而不需要等待前一个请求完成。这解决了HTTP1.1中的队头阻塞问题,提高了性能。
HTTP2.0 还引入了头部压缩(Header Compression)和服务器推送(Server Push)等功能,进一步优化了性能。
关键升级:
二进制分帧
- 优先级
- 多路复用
- 流式传输
头部压缩
服务器推送(已过时)
关键性能卡点:在TCP 层仍然存在队头阻塞问题,因为当一个请求的分帧包丢了,就要等这个包完成重传才能一起提交给浏览器。只是从应用层上解决了并发问题,但是还是受到单个TCP链接的底层限制。
HTTP 3.0
HTTP3.0 协议引入了基于QUIC协议的传输机制,使用UDP协议代替TCP协议进行数据传输,从而解决了TCP协议中的队头阻塞问题,提高了性能和安全性。(了解即可)
GET 方法和 POST 方法区别
GET
GET 是用来请求数据的
GET 方法具有幂等性(不会影响服务器中的资源)
GET 通常情况下把参数写在URL里
GET 请求的数据会被保存在浏览器的历史记录中,也可以保存在CDN中
POST
POST 是用来传输数据的
POST 方法不具有幂等性(可能会影响服务器中的资源)
POST 一般方法把参数写在请求体里
POST 请求的数据不会被保存,而是直接打到服务器
误区:
GET 和 POST 实际上都可以把参数写在URL里或者请求体里,这不是核心差异。
GET 和 POST 都不保证安全,需要靠 HTTPS 的 TLS 协议完成加密才有安全性可言。
POST 方法传递参数的实际大小可能会受到服务器端的限制。如 Nignx 服务最高只支持 1MB 的请求体。
WebSocket
WebSocket 是一种在单个TCP连接上进行全双工通信的协议。它允许客户端和服务器之间进行实时数据交换,适用于需要频繁更新数据的应用,如在线聊天、实时游戏等。
建立在 HTTP 之上(通过 Upgrade 升级)
长连接(区别轮询)
低延迟(无重复握手)
WebSocket 握手过程(重点)
流程:
- 客户端发 HTTP 请求(带 Upgrade)
- 服务端返回 101 Switching Protocols
- 升级为 WebSocket 连接
1 | 👉 关键请求头: |
升级完成后就和 HTTP 协议没关系了。
有了HTTP2,为什么还需要 WebSocket
虽然 HTTP2 也完成了所谓的“全双工”通信和“服务器推”,但是服务器并不能主动向客户端发送消息,必须等到客户端先发起请求之后才能响应,这就导致了服务器无法主动推送消息的情况。而 WebSocket 则允许服务器在任何时候主动向客户端发送消息,实现真正的全双工通信。
服务器推:服务器在响应请求时,顺便把你“可能会用到的资源”提前发给你。Server Push 本质是“资源优化”,不是“通信机制”
DNS服务器用的是什么协议
UDP协议
DNS 查询通常情况下都是一些小的数据包,我们需要保证 DNS 查询的速度。TCP 维护链接状态和频繁的握手、挥手(不同DNS服务器之间查询)会造成很大的性能开销。
ping命令 用的是什么协议?在哪一层?
ping命令用的是ICMP(网际控制报文)协议,是网络层协议
能详细讲一下有限状态机怎么解析http报文吗
HTTP 报文可以分为:请求行、请求头、空行、内容体 四大块内容
那我们就可以根据:空格、回车、换行、空行来做不同状态的转变。
做一个简单的状态机:
解析前:
STATE_BEGIN解析请求行:
STATE_REQUEST_LINE解析请求头:
STATE_HEAD_LINE请求头解析结束:
STATE_HEAD_DONE解析内容体:
STATE_CONTENT解析结束:
STATE_DONE错误状态:
STATE_ERROR
其中 解析请求行 和 解析请求头 还可以根据空格和冒号的存在做更细致的 划分。
假设我们收到了一个POST请求如下:
1 | POST /login HTTP/1.1\r\n |
那么解析过程:
- 起始状态:
STATE_BEGIN读取第一个字符P进入STATE_REQUEST_LINE状态
程序从缓冲区一个字符一个字符读:
P O S T / l o g i n H T T P / 1 . 1 \r \n
当读到 \r\n,说明请求行结束。
然后把这一行拆成三部分:
- method = POST
- path = /login
- version = HTTP/1.1
如果这一行不满足“三段结构”,就进入错误状态 STATE_ERROR。
- 解析请求头:由
\r\n触发到STATE_HEAD_LINE状态
以此类推。
如果解析http请求的时候,用户一次性没传完数据,(如果头部都没传完,请求报文长度字段都没传完,怎么办)
在解析 HTTP 请求时,如果数据没有接收完整,比如请求头还没结束或者 Content-Length 还没读取完整,解析器 不会进行错误处理,而是保留当前解析状态和缓冲区内容。等下一批数据到达后,再从当前状态继续解析。这种方式依赖有限状态机来记录解析进度,可以正确处理 TCP 的半包和粘包问题。
网络层协议
路由表
路由表是网络设备(如路由器)用来决定数据包转发路径的数据结构。它包含了目的地址、下一跳地址、接口等信息。当一个数据包到达路由器时,路由器会根据目的地址在路由表中查找匹配的条目,并根据下一跳地址将数据包转发到下一个设备。
未完待续
路由表为空怎么找到下一跳
当路由表为空时,路由器无法找到匹配的条目来转发数据包,这时会根据默认路由(Default Route)来处理。默认路由是一个特殊的路由条目,通常指向一个网关地址。当没有其他匹配的路由条目时,数据包会被转发到默认网关,由网关负责进一步处理和转发数据包。
未完待续
查看网络状况(ping、Traceroute)
ping 是运行在应用层,但是是基于网络层的ICMP协议的。
Traceroute 就直接工作在网络层
抓包工具
Fiddler,wireshark