《 九 阴 真 经 卷 三 》计算机网络

文章详细介绍了TCP和UDP的区别,包括它们的首部结构、传输特性以及在传输层和应用层中的用途。TCP是面向连接的、可靠的协议,通过三次握手建立连接,而UDP则是无连接的,提供的是尽力而为的传输。此外,文章还提到了HTTP协议的状态码、版本演进以及DNS域名解析的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《 九 阴 真 经 卷 三 》计算机网络

一、传输层

TCP & UDP

TCP

  • TCP是一种面向连接的、可靠的、基于字节流的、无损坏、无间隔、非冗余、按序的传输层协议
  • 一条TCP连接由四元组唯一确定:源IP、目的IP、源端口、目的端口,IP信息在IP协议的首部中,端口信息在TCP协议的首部中

首部

  • TCP首部:
    • 源端口号、目的端口号:16位
    • 序列号、确认应答号:32位,序列号为建立连接时生成的随机数,通过SYN包传递,解决了数据包乱序问题;确认应答号为下次希望收到的序列号,解决了丢包问题
    • 首部长度:4位
    • 六个标志位,各1位
    • 窗口大小:16位
    • 检验和:16位
    • 紧急指针:16位
  • UDP首部:
    • 长度为8字节,64位,包含源端口、目的端口、包长度、检验和
  • UDP首部没有首部长度字段:因为UDP首部定长,TCP首部变长
  • UDP首部有包长度字段,TCP没有

标志位

  • ACK:确认应答,除了最初建立连接时的SYN包之外都必须置1
  • RST:强制断开连接
  • SYN:希望建立连接,同时在序列号字段指定序列号初始值
  • FIN:希望断开连接

TCP和UDP的区别

  • TCP是面向连接的传输层协议,需要先建立连接才能传输数据;UDP不需要
  • TCP只支持一对一;UDP支持一对一、一对多、多对多
  • TCP是可靠通信,数据无差错、不丢失、不重复、按序;UDP仅最大努力交付,但是也可以在应用层基于UDP实现可靠传输,例如QUIC协议
  • TCP首部较长,没有选项时为20Byte,还可能更长;UDP首部为8Byte
  • TCP是流式传输,没有边界;UDP是以数据包为单位传输,有边界
  • TCP数据包大于MSS时,会在传输层拆分;UDP数据包大于MTU时,会在IP层拆分

TCP和UDP各自的用途

  • TCP
    • FTP文件传输
    • HTTP、HTTPs 2.0及之前版本
  • UDP
    • DNS
    • SNMP
    • 音视频:直播、语音通话等

TCP和UDP可以使用同一个端口么

  • 可以
  • 端口是一个传输层的概念,在传输层的意义是区分不同应用的数据包,UDP和TCP在OS内核中是两个独立的模块,主机收到IP数据包后,可以通过IP包头的协议号区分传输层协议,交付给相应模块处理
  • 一句话总结:IP协议包头的协议号字段已经区分了UDP和TCP

TCP三次握手

  • 三次握手是建立连接的过程(下文用C代替Client客户端,S代替Server服务端):
    • 开始C处于CLOSE状态,S处于LISTEN状态
    • C发出SYN包,附带随机生成的序列号,进入SYN_SENT状态
    • S收到后,返回SYN+ACK包,附带等于C序列号+1的应答号,和随机生成的序列号,进入SYN_RCVD状态
    • C收到后,返回ACK包,附带S序列号+1的应答号,进入ESTABLISH状态
    • S收到后,进入ESTABLISH状态,连接建立成功
  • 第三次握手就已经可以携带数据了,前两次不行
  • Linux中查看TCP状态:netstat -napt
  • 为什么是三次握手?
    • 最重要的:防止旧的重复连接成功初始化。例如,C发送了一个序列号为x的SYN包,因为网络原因没有成功传输到S,又发送一个序列号为y的SYN包,x的SYN包成功连接后,S返回了确认号为x+1的SYN+ACK包,C收到后,发现与自己希望收到的y+1ACK包不一致,就会发送RST包断开连接,只有后续ySYN包发送到S后,才能正确建立连接
    • 同步C、S双方的序列号
  • 为什么每次建立连接要重新生成随机的序列号
    • 最重要的:防止历史报文被同一个四元组接收
    • 安全性考虑,防止第三方伪造相同序列号的报文

MSS & MTU

  • MSS:去除IP和TCP首部后,单个数据包中最长的数据长度
  • MTU:整个数据包的最大长度,以太网中通常为1500Byte
  • 为什么IP层会分片,TCP还需要MSS?
    • 如果交给IP层进行分片,如果一个IP数据包丢失,所有IP报文都需要重传,因为IP层没有重传机制
    • TCP层负责分片时,每次重传只重传一个MSS,而非所有分片

半连接队列 & 全连接队列

  • 半连接队列
    • 即SYN队列,存储服务端收到SYN包,已经返回SYN+ACK包但是没有建立连接的对象,收到ACK报文后会从SYN队列中取出对象,加入Accept队列
  • 全连接队列
    • 即Accept队列,每次调用accpet()函数会从Accept队列队列中取出一个对象

SYN攻击

  • 攻击者短时间伪造不同IP地址的SYN报文,占满服务端的半连接队列,后续的SYN包就会被丢弃
  • 避免SYN攻击:
    -扩大半连接队列
    -减少SYN+ACK包重传次数

TCP四次挥手

  • 四次挥手是断开连接的过程
    • 处于连接状态时,C、S都处于ESTABLISH状态。C发出FIN包,进入FIN_WAIT_1状态
    • S收到后,返回ACK包,进入CLOSE_WAIT状态
    • C收到后,进入FIN_WAIT_2状态
    • S发出FIN包,进入LAST_ACK状态
    • C返回ACK包,进入TIME_WAIT状态,等待两个MSL后进入CLOSE状态,S收到ACK后也进入CLOSE状态,连接断开
    • 总结:每个方向都要发出一个FIN和一个ACK
  • 为什么需要四次挥手
    • C发送FIN时,仅代表C没有需要传输的数据了,但是C还可以接收数据
    • S收到FIN,返回ACK后,还可能又数据需要处理或发送,结束后才会发送FIN
  • TIME_WAIT
    • 只有主动断开连接,才有TIME_WAIT状态
    • 为什么要等待2MSL:MSL是报文最大生存时间,报文在网络中存在超过MSL就会被丢弃。2MSL是报文发送加上响应返回的时间
    • 为什么需要TIME_WAIT:
      • 确保本次的报文都死亡,防止历史连接中的数据被后面相同的四元组接收
      • 保证被动断开方,即S端的正常关闭
    • TIME_WAIT过多的危害:
      • 客户端的TIME_WAIT过多:占满了所有端口资源
      • 服务端的TIME_WAIT过多:占用文件描述符、内存等资源
    • 服务端出现大量TIME_WAIT状态的原因:
      • HTTP没有使用长连接,每次HTTP请求、响应都需要重新建立TCP连接
      • HTTP的长连接超时:TCP长连接在长期没有新的HTTP请求时会断开
      • HTTP长连接的请求数量达到上限:一条TCP长连接上能处理的最大请求数量有限,超出限制时会主动关闭连接,在QPS很高时就可能频繁断开长连接
    • 服务端出现大量CLOSE_WAIT状态的原因:
      • 服务端程序没有调用close()函数,来发出FIN包
  • TCP保活机制
    • 如果一条TCP连接的一个时间段内没有活动,就会发送一个探测报文,如果若干个探测报文都没有被响应,就会认为当前TCP连接已经死亡,从而断开TCP连接

TCP网络编程

  • TCP网络编程函数:
    • C和S都初始化socket,获取socket的文件描述符
    • S调用bind(),将socket绑定到指定的IP+端口
    • S调用listen(),开始监听端口
    • S调用accept(),尝试从半连接队列获取连接
    • C调用connect(),发起三次握手
    • S的accept()函数返回用于传输的socket的文件描述符
    • C调用write()写入数据,S调用read()读取数据
    • C调用close(),发起四次挥手,此时S再调用read()读取数据,会读取到EOF,在S处理结束后,也调用close(),关闭连接
  • 上述流程中出现了两个socket,一个是监听端口的socket,另一个是已经完成连接的socket
  • 第二次握手成功时,C端的connect()就会返回;三次握手成功后,S端的accept()才会返回
  • EOF End Of File,代表连接上已经没有其他数据
  • 没有accept()也能建立TCP连接,accept()只是从已经建立好的TCP队列中拿出一个
  • 没有listen()也能建立TCP连接,即两个客户端之间的TCP连接,或客户端与自身建立的TCP连接

TCP重传机制

  • 超时重传:发出数据包一段时间后,没有收到应答,会触发超时重传。超时时间通常设置为数据包的一个RTT Round Trip Time 往返时延,即发出数据包到接收到确认的时间差值
  • 快速重传:接收端收到不符合预期的数据包之后,会返回最后一个符合预期的数据包的确认应答号。发送端连续收到三个相同的确认应答后,会触发重传机制
  • SACK 选择性确认:快速重传机制下,只重传丢失的数据。通过在首部的选项里增加SACK实现
  • Duplicate SACK:使用了 SACK 来告诉「发送方」有哪些数据被重复接收了

TCP滑动窗口

  • 窗口是指无需确认应答就可以发送出去的序列号最大值
  • 发送方和接收方都会维护自己的滑动窗口,首部中会带有一个字段,标识窗口大小,用于接收端告诉发送端自己的剩余缓冲区大小,发送方的滑动窗口不能超过接收方的滑动窗口
  • 发送方会在没有收到ACK的情况下,把窗口里的数据包全部发出,当发送方接收到ACK时,会根据这个ACK扩大滑动窗口。所以发送方的数据包可以分为四部分:
    • 滑动窗口左侧:已经发出并收到确认
    • 滑动窗口右侧:还不允许发出
    • 滑动窗口内:已经发出但未收到确认
    • 滑动窗口内:尚未来得及发出
  • 接收方的数据包可以分为三部分:
    • 滑动窗口左侧:已经接收到的、已确认数据
    • 滑动窗口右侧:还不允许接收的数据
    • 滑动窗口内:允许接收但尚未接收到的数据
  • 滑动窗口大小会收到OS的缓冲区大小控制

TCP的流量控制

  • 滑动窗口机制

TCP窗口关闭

  • 接收方接收数据后,返回的ACK报文在网络中丢失了,造成发送方无法发送数据,接收方也接收不到数据,形成了死锁
  • 解决:任何一方收到零窗口通知后,都会启动计时器,超时后发送窗口探测报文,对方会响应自己的窗口大小

TCP糊涂窗口综合征 & Nagle算法

  • 接收方处理数据的速度过慢,导致接收窗口非常小,每次发送方只能发送很少量的数据
  • 解决:
    • 设定最小窗口大小,窗口过小时,会发送零窗口通知
    • Nagle算法:必须满足下述两条才能发送数据:
      • 窗口和数据都大于某个下限
      • 收到了之前所发数据报的ACK
  • Nagle算法会导致延迟增大,所以某些场景不会开启Nagle算法,诸如SSH和TELNET

TCP拥塞控制

  • 拥塞窗口CWND:在发送时,真正的有效窗口大小是上述滑动窗口和拥塞窗口的较小值
  • 控制拥塞窗口大小的四个机制:
    • 慢启动:拥塞窗口大小从1开始,每次收到一个ACK会增加1,所以实际上CWND每次都会翻倍,呈现指数增长
    • 拥塞避免:CWND超过慢启动门限后会开始拥塞避免,每次收到一个ACK后,CWND增加1/CWND,实际上每次增加1,呈现线性增长
    • 快重传:
      • 发生超时重传时,慢启动门限会被设置为CWND的1/2,CWND会被重置为初始值,一般为1
      • 收到连续三个相同的ACK后,立即开始重传
    • 快恢复:慢启动门限和CWND都降低至原来的1/2,开始拥塞避免
    • 总结:刚开始时,CWND会从一个较小的初始值以指数速度迅速增长至慢启动门限,然后触发拥塞避免,转为线性增长。发生超时这种严重问题时,会重新开始慢启动;发生连续收到三个相同ACK这种不严重问题时,会触发快恢复。能收到三个相同ACK依赖于快重传机制

TCP抓包工具

  • tcpdump、Wireshark

面向字节流与面向报文

  • UDP协议,OS完全不会拆分消息,每个UDP报文就是一个用户消息的边界,每次调用recvfrom()会从OS的队列中取出一个UDP报文
  • TCP协议,OS会将用户的消息拆分成多个TCP报文,发送时也不会考虑报文的完整性
  • 粘包:两个用户消息被分到一个TCP报文进行传输
  • 粘包解决:
    • 固定消息长度
    • 使用特殊字符作为消息边界:HTTP协议的回车和换行符就是消息边界
    • 自定义消息结构,使用字段标定消息长度

二、应用层

HTTP

HTTP基本概念

  • HTTP是HyperText Transfer Protocol 超文本传输协议

五类状态码

  • 1xx:提示信息
  • 2xx:成功
    • 200:最常见的成功状态码
  • 3xx:重定向
    • 302:临时重定向,响应头中会带有Location,指明跳转的URL,浏览器会自动跳转
  • 4xx:客户端错误
    • 403:禁止访问
    • 404:资源未找到
  • 5xx:服务端错误
    • 502:网关(常为NGINX)正常,但是后端服务出错

方法

  • GET、POST、DELETE、PUT、
  • GET和POST的区别:
    • GET的参数一般都携带在URL里明文传输,只能是ASCII格式,且浏览器对URL长度有限制(协议本身并没有);POST请求的参数一般在请求体内,可以是任意格式,大小无限制
    • GET请求理论上也可以带有请求体,POST请求也可以在URL里携带参数

HTTP缓存

  • 分为两种:
    • 强制缓存:响应码为200(from disk cache),浏览器在第一次访问服务器时,服务器除了返回数据,还会返回一个过期时间,浏览器再次访问时会计算是否过期,未过期就直接使用浏览器本地缓存,否则重新请求服务器
    • 协商缓存:响应码为304,是由服务端告知浏览器可以使用浏览器本地缓存

HTTP的版本演进

  • HTTP/1.1:
    • 默认开启了长连接
    • 具有管道网络传输功能,但默认不开启。管道网络传输是在同一个TCP连接内,不等待响应就发送多个请求,可以避免请求的队头阻塞,即某一个请求迟迟不返回,导致后续的请求无法发出的问题
  • HTTP/2.0:
    • 头部压缩:如果发出多个请求,协议会消除重复的部分。其实现为HPACK算法,即C和S都维护一张头信息表,借助索引号映射
    • 二进制格式:不像HTTP/1.1版本的纯文本形式,HTTP/2.0的头信息和数据体都是二进制格式。例如状态码200用字符表示需要3Byte,用二进制表示需要1Byte
    • 并发传输:允许并行交错的发送响应和请求,借助StreamID的机制实现,彻底解决了请求和响应的队头阻塞问题,但是还有TCP层的队头阻塞问题,当某个请求/响应的TCP数据包丢失时,依然会阻塞后续请求/响应
    • 服务端可以主动推送内容
  • HTTP/3.0:
    • 传输层协议改为了基于UDP的QUIC协议(一种可靠的UDP协议),彻底解决了所有队头阻塞问题
    • 之前的版本TCP握手和TLS握手需要依次进行,HTTP/3.0在传输前需要QUIC握手,QUIC协议已经包含了TLS,在QUIC握手的过程中就完成了密钥的协商
    • 连接迁移:TCP协议是通过四元组标定的,比如切换4G和Wifi时更改了IP,就必须断开再重建TCP连接。因为QUIC协议没有使用四元组标定,而是使用连接ID,所以IP变化后只要连接ID不改变,依然可以复用原来的连接

Cookie与Session

HTTPs

基本概念

  • HTTPs协议在传输层和应用层之间加入了SSL/TLS安全协议,使得报文可以加密传输
  • HTTP默认端口为80,HTTPs为443
  • HTTP连接只需要TCP三次握手,HTTPs还需要SSL/TLS握手

对称加密 & 非对称加密 & 混合加密

  • 对称加密:只使用一个密钥,密钥必须保密
  • 非对称加密:使用两个密钥,公钥和私钥
  • 混合加密:在通信前用非对称加密交换会话密钥,通信过程中全部使用对称加密的会话密钥加密

SSL/TLS

  • 基本流程
    • 客户端向服务端索要并验证服务器的公钥
    • 双方协商产生会话密钥
    • 采用会话密钥进行加密通信
  • TLS握手
    • 一共需要四次通信,常用的有RSA算法和ECDHE算法
    • 第一次 Client Hello:C向S发送TLS协议版本、C生产的随机数、支持的密码套件列表
    • 第二次 Server Hello:S收到请求后,返回确认TLS版本、S生产的随机数、确认密码套件列表、S的数字证书
    • 第三次 客户端回应:C收到S的回应后,利用上述三个随机数计算出会话密钥,并确认数字证书的真实性,确认之后从数字证书中取出S的公钥,用它加密报文发送下列信息:
      • 除上述两个之外第三个随机数
      • 加密通信算法改变的通知,表示之后的信息会用会话密钥加密
      • 客户端的握手结束通知
    • 第四次 服务端回应:S收到C发来的,被公钥加密后的第三个随机数,用S的私钥解密之后,通过约定的加密算法,计算出会话密钥,向C发送
      • 加密通信算法改变的通知
      • 服务端的握手结束通知
    • 在这四次握手之后,C和S都通过三个随机数计算出了相同的会话密钥,之后的通信就是根据这把密钥的对称通信了。所以TSL握手的过程是先利用非对称加密协商密钥,再用协商出来的密钥进行对称加密通信
  • 数字证书 & CA
    • 数字证书通常包含:
      • 公钥
      • 持有者信息
      • CA的信息
      • CA的数字签名即签名算法
      • 有效期
      • 其他信息
    • CA 证书认证机构
    • 签发数字证书的过程
      • CA把数字证书的所有信息打包,计算出一个哈希值,用私钥对这个哈希值加密,生成数字签名添加到证书上
    • 验证数字证书的过程
      • 客户端收到证书后,用同样的哈希算法计算出一个哈希值,再用CA的公钥解密数字签名,得到另一个哈希值,比较这两个哈希值
    • 总的来说,验证的过程是CA用私钥加密哈希值,作为数字签名,而客户端用CA的公钥解密数字签名,得到并对比哈希值的过程。验证是私钥加密,公钥解密;TLS协商会话密钥是公钥加密,私钥解密;公钥和私钥是属于同一方的,用其中哪一个来解密取决于加密信息的发送方向

RPC

概念

  • RPC并不是一种协议,而是Remote Procedure Call远程过程调用,是一种调用方式。但是具体的实现比如Thrift、gRPC、bRPC就是协议
  • 大部分RPC底层协议基于TCP,也有基于HTTP和UDP的
  • RPC主要用于微服务之间的通信

服务发现

  • 找到对应服务的IP和端口的过程就是服务发现
  • HTTP中,如果有服务的域名,就可以通过DNS服务去解析IP地址
  • RPC中,一般有某个专门的中间服务保存服务名和IP信息,有可能是ETCD、Redis…DNS也可以作为RPC的服务发现组件

传输内容序列化方式

  • HTTP使用JSON作为Body的序列化方式
  • RPC使用ProtoBuf作为序列化方式,定制程度更高,性能更佳
  • 实际上HTTP/2.0的性能已经非常优异了,所以gRPC实际底层就是使用HTTP/2.0

三、网络层

DNS

概念

  • DNS是域名解析
  • 域名都是用句点来分割的,越往右层级越高
  • 客户端和本地DNS服务器进行的是递归查询,由本地DNS服务器代替客户端去进行迭代查询,即从高到低的查询从根域名服务器到低层根域名服务器,每次查询更低一层DNS服务器的IP地址,最终查询到目标域名的IP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值