导图社区 大厂SSPoffer 复习资料 - 计算机网络
博主获取大厂 腾讯,美团,字节,B站,超参数等大厂ssp的计算机网络复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
编辑于2024-12-08 17:58:32博主获取多个大厂包括 腾讯,字节,B站,超参数等ssp的mysql复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
博主获取多个大厂包括 腾讯,字节,B站,超参数等ssp的redis复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
博主获取大厂 腾讯,美团,字节,B站,超参数等大厂ssp的计算机网络复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
社区模板帮助中心,点此进入>>
博主获取多个大厂包括 腾讯,字节,B站,超参数等ssp的mysql复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
博主获取多个大厂包括 腾讯,字节,B站,超参数等ssp的redis复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
博主获取大厂 腾讯,美团,字节,B站,超参数等大厂ssp的计算机网络复习资料,希望这份资料能够为求职者提供一个全面的学习框架,帮助大家面试中脱颖而出,成功获得心仪的offer。
计算机网络
2.0 计算机网络的基础设备
计算机之间直链
C = n(n-1)/2
集线器:为了减少直连的线
加个中间层
这时候集线器就诞生了
缺点
1. 每次发送消息都是群发
2. 是半双工的
交换机 (不关心IP) MAC层
1. 使用MAC地址
MAC地址和端口相连
2.全双工
3. 支持桥接
也就是交换机和交换机之间直连
缺点
还是不够全世界的网络,MAC端口表有上限,几万
后来的MAC对应的端口会覆盖旧地址
并且使用交换机,可能造成链路过长
路由器
这个路由器不是家用路由器
是专门的处理网络连接的路由器
家庭路由器和这个路由器都会进行IP的转换NAT
基于路由算法
管理不同的网络设备
路由器会给不同网络分配不同的网段
网关
网关是一种通信节点,用于在不同的网络或子网之间提供连接。它通常是网络中的第一个路由器,用于连接本地网络和外部网络。
在家庭或小型办公室网络中,网关通常是路由器的一部分,提供单一的入口点来访问外部网络,如互联网。
实现:流量控制,负债均衡,请求预处理,协议转换等功能
DHCP服务器
主机开机通过发送一个发现报文,请求DHCP服务器,请求DNS,IP,MASK,GateWay,可能网络中有多个DHCP服务器,一般选择最先到达的IP地址
确认IP后,广播确认报文,让对应的DHCP服务器接收到确认报文,DHCP也返回确认报文,通过四次通信获取IP地址
1. 小型路由器内置了DHCP服务器功能 2. 大型网络有独立的服务器运行DHCP功能
2.1 TCP/IP模型
应用层
HTTP、FTP、Telnet、DNS、SMTP
1. HTTP (HyperText Transfer Protocol, 超文本传输协议)
用于从网络传输超文本到本地浏览器的传输协议。
它使得网页浏览器能够获取服务器上的网页文件,并将其显示给用户。
2. FTP (File Transfer Protocol, 文件传输协议)
用于在网络上的计算机之间传输文件。
它提供了文件的上传和下载功能,常用于网站管理和文件共享。
3. Telnet (远程登录协议)
用于远程登录到服务器,通过一个命令行界面与远程系统交互。
尽管Telnet在某些情况下仍然被使用,但现在SSH(安全外壳协议)更常用于安全地进行远程登录。
4. DNS (Domain Name System, 域名系统)
用于将域名转换为IP地址。
它作为互联网的地址簿,将用户的域名(如www.example.com)解析为机器可读的IP地址。
5. SMTP (Simple Mail Transfer Protocol, 简单邮件传输协议)
用于发送电子邮件。
它定义了邮件服务器之间电子邮件消息的发送和接收规则。
这个是用户态,应用层以下操作是内核态
传输层
TCP
MSS
确认应用 所以要有端口
对接发送端的每一个浏览器的标签页都是一个独立的进程,操作系统会给每个标签页分配临时端口
网络层
IP
MTU
以太网中是1500字节
1.5K
寻址
找到互联网中的主机号
路由
修改数据包的mac地址
静态路由算法主要有洪泛法,随机走动法,最短路径法,基于流量的路由算法
1.洪泛法(Flooding)
节点收到一个报文分组后,向所有可能的方向复制转发。每个节点不接受重复分组,网络局部故障也不影响通信,但大量重复分组加重了网络负担。这种方法适宜于网络规模小,通信负载轻,可靠性要求极高的通信场合——如军用通信中常用。
2.随机走动法(Random Walk)
其改进方法是选择前进方向的扩散法,可大大减少重复分组的数量。
3.最短路径法(Shortest Path,SP)
一般来讲,网络节点直接相连,传输时延也不是绝对最小,这与线路质量、网络节点“忙”与“闲”状态,节点处理能力等很多因素有关。定量分析中,常用“费用最小”作为网络节点之间选择依据,节点间的传输时延是决定费用的主要因素。
最短路径法,是由Dijkstra提出的,其基本思想是:将源节点到网络中所有节点的最短通路都找出来,作为这个节点的路由表,当网络的拓扑结构不变、通信量平稳时,该点到网络内任何其它节点的最佳路径都在它的路由表中。如果每一个节点都生成和保存这样一张路由表,则整个网络通信都在最佳路径下进行。每个节点收到分组后,查表决定向哪个后继节点转发。
4.基于流量的路由算法(Flow-based Routing,FR)
SP算法只考虑网络拓扑结构、寻找最短路径,没有考虑网络流量、负载对路由选择的影响,而FR算法就结合了网络拓扑结构和通信流量两方面的因素进行路由选择。
FR算法需要知道网络拓扑结构、节点之间的平均流量、各条线路的容量,然后在此基础上采用适当的选择算法,从而找出最佳路由。
FR算法的基本原理是根据知道一条线路的负荷和平均流量,用排队计算出该线路的分组平均时延,再由所有线路的平均时延直接计算出流量加权平均值,从而得到整个网络的平均分组时延。此方法可使网络通信量更加平衡,得到较小的平均分组时延。
动态路由算法大致可以分为两类:
距离矢量路由算法
链路状态路由算法
路由不一定对称
确认主机所以要有IP
负责将数据进行传输
网络接口层
有了MAC为什么还要IP地址
因为二层协议不止MAC协议,再往上面封装一次产生IP协议
在 IP 头部的前面加上 MAC 头部,并封装成数据帧(Data frame)发送到网络上
以太网在判断网络包目的地时和 IP 的方式不同,MAC 头部采用相匹配的方式将包发往目的地
ARP IP-MAC
TCPIP四层模型/ OSI七层模型
应用层和传输层的负载均衡
四层负载均衡(Layer 4 Load Balancing)是在传输层(Transport Layer)上进行负载均衡的技术。它基于源IP地址、目标IP地址、源端口和目标端口等信息来进行负载均衡。四层负载均衡器能够根据这些信息将传入的请求分发到后端服务器集群中的某个节点,以实现负载均衡。它主要关注网络连接的处理,不考虑应用层协议的具体内容。
七层负载均衡(Layer 7 Load Balancing)是在应用层(Application Layer)上进行负载均衡的技术。它不仅考虑了传输层的信息,还深入到应用层协议的内容,如HTTP报文中的URL、请求头、Cookie等信息。七层负载均衡器能够根据这些应用层信息进行智能分发,使得负载均衡更加精细化。七层负载均衡器可以根据请求特征进行内容过滤、请求分发、会话保持等操作,以提供更高级的负载均衡功能。
总结来说,四层负载均衡主要关注网络连接的处理,基于传输层信息进行分发;而七层负载均衡在四层的基础上深入到应用层,根据应用层协议的内容进行智能分发,提供更丰富的负载均衡功能。选择使用哪种负载均衡技术取决于具体的应用需求和场景。
电商服务端
DNS的作用这里无需赘述,但是比较特别的是,DNS解析出来的的结果,并不是单纯地写成IP,而是写成了VIP--虚拟IP。在IPV4里,IP是很珍贵的,为了收敛IP,公司会将所有服务的接入都收敛到数量比较有限的几个IP。DNS会将域名解析到某个机房上,例如廊坊。
TTGW是内部的网关,进行负债均衡,并且去掉了外网,避免了DDos攻击。
DDoS(Distributed Denial of Service) 攻击,即分布式拒绝服务攻击是黑客通过控制分布在互联网各处的僵尸网络对目的服务器发起大量恶意请求,导致服务器无法响应正常业务请求,造成拒绝服务的攻击手法。
TLB
http反向代理
TTGW为4层负载均衡网关,需要部署在7层负载均衡TLB集群之前,TTGW将作为外网的统一入口将负载均匀分配给TLB机器。为什么具有外网接入的TLB集群需要在前面加一层TTGW?原因如下: 1. 我们的数据中心中外网的机器数量是有一定限制的,TLB集群如果都使用外网机器进行扩容的话,外网机器资源消耗快,不足以灵活应对像春节这样的活动。 2. TTGW只处理到数据包的4层,处理性能更强,能够收敛外网接入VIP。 1. 目前TLB集群中每8台为一组,每组TLB机器向外发布不同的外网IP,而TTGW集群对接整个TLB集群只需要发布一组外网IP即可。 2. 像阿里的CDN,最多允许配置的动态回源IP为10个,TLB集群中8个为一组发布不同的外网IP,会使得有的大流量域名扩容不便。 3. 由于TLB集群按照8台为一组向外发布外网IP,那么当域名很多时,在对新域名的解析IP或者动态加速IP进行配置时就很难保证后端的TLB集群各机器负载均衡。 3. TTGW的接入能够通过不同的weight值设置后端TLB集群各个机器的负载,运维操作方便。 总之,为了运维,扩容和运行的灵 活性,目前四大app的TLB前端已基本完成TTGW的部署。部署完TTGW后的一个重要工作便是把域名解析的IP或动态加速回源IP由TLB迁移到TTGW,然后TTGW再把流量打向域名所属的TLB集群。接入侧架构演进的示意图如下所示,右侧为最终需要达到的状态。
AGW
AGW(Api Gateway)-般而言,TLB之后直接就可以对接业务api服务了。但为了提供通用的解决方案,例如登陆态校验、防抓取、流量灰度、接口级的灰度等,APIGateway将这些功能都进行了收归,让业务方可以不用处理这些细节。
2.2 键入网址到网页显示的过程
第一步是解析URL
通过URL确定服务器的域名,服务器文件路径
如果没有文件路径,则访问根目录默认的文件
生成请求报文
GET还是POST请求
负载的数据有哪些
接受什么格式的内容
接受什么压缩格式
第二步查询真实的地址
DNS
域名转为IP
DNS在进行区域传输的时候使用TCP,普通的查询使用UDP
DNS 中的域名都是用句点来分隔
DNS专门用来查询域名和IP对应关系的服务器
域名有一个层级结构
根域名服务器
顶级域名服务器
一级域名服务器
权威域名服务器
二级域名服务器
这个是迭代查询
还有一种递归查询
如果本地DNS服务器没有缓存所请求的信息,它会代表客户端向根服务器、TLD服务器和权威DNS服务器发出查询,直到获得所需信息,然后将这些信息返回给客户端
DNS缓存分别在
浏览器缓存
操作系统
host文件
这三个都没有才去问DNS服务器
第三步将调用操作系统的协议栈
DNS 获取到 IP之后,浏览器通过调用Socket库,来委托协议栈工作
是应用层和传输层之间的一组抽象接口,用于不同应用程序之间的通信
使用套接字进行通信和数据的接受和发送
建立完之后就可以进行
send操作
receive操作
1. 套接字创建(Socket Creation)
服务器端:
创建套接字:使用 socket() 函数创建一个新的套接字。
绑定地址:使用 bind() 函数将套接字与特定的 IP 地址和端口号绑定。
监听:通过 listen() 函数使得套接字进入监听状态,等待客户端的连接请求。
客户端:
创建套接字:同样使用 socket() 函数创建一个新的套接字。
2. 连接建立(Connection Establishment)
连接请求:使用 connect() 函数向服务器的套接字发送连接请求。
接受连接:使用 accept() 函数接受客户端的连接请求。此函数在连接建立之前是阻塞的。
3. 数据传输(Data Transfer)
发送和接收数据:双方可以使用 send() 和 recv()(或类似的 write() 和 read())函数来发送和接收数据。
4. 关闭连接(Connection Termination)
结束通信:使用 close() 函数关闭套接字,结束通信会话。
1. Socket
socket是对TCP/IP协议的封装,它的出现只是使得程序员更方便地使用TCP/IP协议栈而已。socket本身并不是协议,它是应用层与TCP/IP协议族通信的中间软件抽象层,是一组调用接口(TCP/IP网络的API函数)
内核设计
数据结构
定义sock为最基础的数据结构,来定义可能会用到的收发缓冲区。
之所以没有定义ip和port是因为不是所以的socket都是网络连接,比如UNIX DOMAIN SOCKET,用于本机器进程通信。
inet_sock继承sock加入ip和sort字段。
inet_connection_sock继承inet_sock加入accept队列,数据包分片和握手失败重试次数
tcp_sock继承inet_connection_sock,加入了TCP特有的滑动窗口
API设计
因为socket是读写,文件系统也是读写(Linux一切皆文件),索性封装到操作系统内核中,通过fd唯一标识sock。有了数据结构我们需要定义api来给应用层调用,比如send,recv,bind,listen,connet
网络传输(以TCP为例)
通过connect(句柄fd,ip,port)找到内核中的sock结构
发起三次握手建立连接
send(句柄,消息)向缓冲区(本质上是一个链表)加入消息数据。
recv(句柄)从发送缓冲区中找到消息数据。
唯一标记客户端
通过发送发ip,port,接收方ip和port来标记唯一客户端
通过四元组生成hash key,这样通过hashtable快速拿到客户端
文件描述符(File Descriptor, FD):是操作系统分配的用于标识和管理打开的文件、套接字、管道等 I/O 资源的一个非负整数。
套接字(Socket):是网络通信的端点,用于在不同主机之间进行数据传输。套接字通过系统调用(如 socket)创建,并被操作系统分配一个文件描述符。
创建套接字
在类 Unix 系统(包括 Linux)中,使用socket系统调用来创建一个套接字。这个调用返回一个文件描述符,用于标识创建的套接字。
socket 方法的原型
int socket(int domain, int type, int protocol);
创建之后的效果
1. 文件描述符:socket 调用返回一个文件描述符,标识创建的套接字。这是一个非负整数,该文件描述符唯一标识这个套接字。后续的套接字操作(如绑定、监听、连接、发送和接收数据)都将使用这个文件描述符。
2. 资源分配:操作系统分配必要的资源来管理套接字,包括内存、缓冲区等。套接字本身是一个内核对象,用于管理网络通信。
3. 协议栈初始化:根据指定的协议族和协议类型,操作系统初始化相应的协议栈。例如,对于 AF_INET 和 SOCK_STREAM,初始化 TCP 协议栈。
后续操作
1. 绑定地址和端口(bind):将套接字绑定到特定的地址和端口。
struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); if (bind(sockfd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); close(sockfd); exit(EXIT_FAILURE); }
2. 监听连接listen:使套接字进入监听模式,准备接受连接请求。
if (listen(sockfd, 3) < 0) { perror("listen failed"); close(sockfd); exit(EXIT_FAILURE); }
3. 接受连接accept:接受一个连接请求,并返回一个新的文件描述符,用于与客户端通信。
int new_socket; struct sockaddr_in client_address; socklen_t addrlen = sizeof(client_address); new_socket = accept(sockfd, (struct sockaddr *)&client_address, &addrlen); if (new_socket < 0) { perror("accept failed"); close(sockfd); exit(EXIT_FAILURE); }
4.连接到服务器:客户端使用 connect 函数连接到服务器。
struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(8080); inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr); if (connect(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) { perror("connect failed"); close(sockfd); exit(EXIT_FAILURE); }
5. 发送数据(send)和接收数据(recv):通过套接字发送和接收数据。
char *message = "Hello, World!"; send(new_socket, message, strlen(message), 0); char buffer[1024] = {0}; int bytes_received = recv(new_socket, buffer, sizeof(buffer), 0); printf("Received: %s\n", buffer);
6. 关闭套接字close:关闭套接字,释放资源。
close(new_socket); close(sockfd);
调用 socket 方法后,操作系统会创建一个套接字并返回一个文件描述符。这个文件描述符用于标识和管理套接字,后续的网络操作(如绑定、监听、接受连接、发送和接收数据)都基于这个文件描述符。通过这些操作,可以实现网络通信和并发连接处理,构建功能丰富的网络应用。
2. IO多路复用
IO多路复用
是一种操作系统层面的机制,它允许应用程序同时监视多个IO操作
IO操作不仅包括与外部设备(如硬盘、打印机等)的交互,也包括与操作系统内核进行数据交换的各种操作,特别是网络通信
IO操作
文件IO:对文件系统进行的读写操作。
网络IO:通过网络发送和接收数据,这包括与远程机器的TCP/IP套接字通信。
设备IO:与硬件设备(如串口、USB设备等)的交互。
管道和消息队列:进程间通信的机制。
"IO"特别强调的是数据的准备状态,即数据是否已经准备好被读取或写入。这种状态的检测对于提高应用程序的效率至关重要
基本概念
IO源:可以是文件描述符、套接字等,它们是操作系统用来标识IO设备的抽象。
就绪状态:当IO源可以进行读取或写入操作时,称其为“就绪”状态。
工作机制
1. 注册IO源:应用程序将需要监视的IO源注册到IO多路复用系统中。
2. 阻塞等待:应用程序调用IO多路复用函数,进入阻塞状态,等待任何一个注册的IO源变为就绪状态。
3. 通知:当任何一个IO源准备好读取或写入时,IO多路复用系统会通知应用程序。
4. 处理IO请求:应用程序从IO多路复用系统中获取就绪的IO源,并进行相应的读取或写入操作。
优化
缓冲区
双缓冲:为了进一步优化,系统可能使用双缓冲技术。即在一个缓冲区正在被写入或读取的同时,另一个缓冲区可以准备下一个数据块,这样可以实现I/O操作的并行处理,进一步提高效率。
消息队列
一个进程虽然任一时刻只能处理一个请求,但是处理每个请求的事件时,耗时控制在 1 毫秒以内,这样 1 秒内就可以处理上千个请求,把时间拉长来看,多个请求复用了一个进程,这就是多路复用,这种思想很类似一个 CPU 并发多个进程,所以也叫做时分多路复用。
进程可以通过一个系统调用函数从内核中获取多个事件。
select、poll、epoll
select
select同时监听多个文件描述符的就绪状态
使用位图遍历就绪状态
连接数量少还行,太多了性能下降并且最多只能支持2048个
poll使用链表结构来表示文件描述符的状态
没有最大连接数数量
select 和 poll 并没有本质区别,它们内部都是使用「线性结构」来存储进程关注的 Socket 集合
epoll
epoll使用的不是轮询而是回调,监听真正触发的事件
epoll 在内核里使用「红黑树」来关注进程所有待检测的 Socket,红黑树是个高效的数据结构,增删改一般时间复杂度是 O(logn),通过对这棵黑红树的管理,不需要像 select/poll 在每次操作时都传入整个 Socket 集合,减少了内核和用户空间大量的数据拷贝和内存分配。
epoll 支持两种事件触发模式,分别是边缘触发(edge-triggered,ET)和水平触发(level-triggered,LT)。
使用边缘触发模式时,当被监控的 Socket 描述符上有可读事件发生时,服务器端只会从 epoll_wait 中苏醒一次,即使进程没有调用 read 函数从内核读取数据,也依然只苏醒一次,因此我们程序要保证一次性将内核缓冲区的数据读取完;
epoll_wait只苏醒一次
边缘触发的意思是只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。
使用水平触发模式时,当被监控的 Socket 上有可读事件发生时,服务器端不断地从 epoll_wait 中苏醒,直到内核缓冲区数据被 read 函数读完才结束,目的是告诉我们有数据需要读取;
epoll_wait不断苏醒
水平触发的意思是只要满足事件的条件,比如内核中有数据需要读,就一直不断地把这个事件传递给用户
举个例子,你的快递被放到了一个快递箱里,如果快递箱只会通过短信通知你一次,即使你一直没有去取,它也不会再发送第二条短信提醒你,这个方式就是边缘触发;如果快递箱发现你的快递没有被取出,它就会不停地发短信通知你,直到你取出了快递,它才消停,这个就是水平触发的方式。
select/poll 只有水平触发模式,epoll 默认的触发模式是水平触发,但是可以根据应用场景设置为边缘触发模式。
多线程和IO多路复用
1. 多线程
多线程是指一个进程中可以同时运行多个线程,每个线程可以执行不同的任务。
在QQ中,可能会有多个线程分别处理不同的任务,例如:用户界面的更新、网络通信、文件读写等。
多线程允许QQ同时响应用户操作和进行后台数据处理,提高应用程序的响应性和效率。
2. IO多路复用
IO多路复用是一种技术,允许单个线程或进程同时监视多个IO操作(如网络连接、文件操作等)。
在QQ中,如果需要同时处理多个网络连接(例如,同时接收来自不同好友的消息),IO多路复用可以使得一个线程能够等待多个IO源变为就绪状态,并在任何一个IO源就绪时立即响应。
这可以减少创建多个线程来分别处理每个连接的需要,从而降低资源消耗和提高效率。
3. 异步编程模型
Reactor
Reactor模式
1. 在Reactor模式中,有一个主要的事件循环(Event Loop),负责监听和分发事件。它通过使用非阻塞I/O和事件通知机制来实现高效的事件驱动。主要包含以下组件:
2. 事件循环(Event Loop)
是Reactor模式的核心。
负责监听和分发事件,通常是一个无限循环。
从操作系统或框架底层获取就绪的I/O事件,并将这些事件分发给相应的处理程序进行处理。
3. 事件源(Event Sources)
是产生事件的对象或者组件。
可以是网络套接字、文件描述符、定时器等。
事件源会将事件通知给事件循环,然后由事件循环分发给相应的事件处理程序。
4. 事件处理程序(Event Handlers)
是对特定事件进行处理的模块。
负责处理接收到的事件,执行相应的操作和业务逻辑。
可以是回调函数、方法或者独立的处理器对象。
Reactor模式的工作流程
1. 事件源产生事件
事件源(如网络套接字、文件描述符、定时器等)产生事件。
2. 事件源将事件通知给事件循环
事件源将产生的事件通知给事件循环。
3. 事件循环监听并接收到事件
事件循环持续监听事件源,接收到事件后处理。
4. 事件循环分发事件
事件循环根据事件的类型和注册的事件处理程序,将事件分发给相应的事件处理程序。
5. 事件处理程序处理事件
事件处理程序接收到事件后,执行相应的操作和业务逻辑。
6. 处理完事件后返回事件循环
事件处理程序处理完事件后,返回到事件循环,等待下一个事件的到来。
Ping-Pong"模式是双向的请求和响应通信模式,请求方发送请求,响应方返回响应。
"One-Way"模式是单向的通信模式,请求方发送请求后不需要等待响应。
4. 之间关系
Socket和IO多路复用是基础
I/O多路复用:是一种在单线程中同时监视多个文件描述符的方法
One way、Ping-pong、Reactor等模式是基于这些基础和工具的具体编程模型
第四步因为HTTP是基于TCP协议传输的
在传输之前需要TCP建立连接,三次握手
前两次是不带数据的 第三次握手可以带数据
在前面的HTTP请求响应包头添加TCP的头部
查看TCP链接
netstat - napt
TCP数据包能容纳的长度
网络包(MTU)的长度为1500字节
TCP包(MTU-TCP和IP头部长度)
第五步需要建立IP链接
包含源IP和目的IP
源IP是客户端输出的IP地址
目的是通过DNS解析出来的IP
协议号
因为是TCP协议所以是06
当有多个网卡的时候
根据路由表来判断哪个作为源IP
使用route -n输出路由表
根据目标地址的网络号(IP号和子网掩码做且运算),来匹配
如果匹配不到就用默认路由,比如eth 0网卡
IP是终点到起点
第六步 网卡填上MAC
封装MAC头
发送方MAC地址就在发送地方的网卡里
接受方的MAC地址就根据ARP协议找到
ARP协议找不到对应的IP就会将路由器的MAC地址添到数据包头部
TCP/IP协议类型只使用
IP协议
ARP协议
用来IP转为MAC地址
同网段发ARP获取目标设备的mac
不同网段则查找本身的路由表,则通过获取网关MAC,发送给网关传给目标网段
有arp缓存表
通过广播IP地址获取MAC地址
arp -a查看ARP缓存内容
在操作系统中
MAC是物理设备到下一个物理设备的
第七步 从网卡转发
将数字信号转为电信号
加上报头和起始帧分界符
末尾的贞校验序列
路由器或者主机接收数据包的时候,根据MAC头部判断是不是发给自己的,交换机全部接收
第八步 进入交换机
不判断直接全部放入缓存区
根据MAC地址表来判断转发到哪个端口
如果不存在呢
这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。
这样做不会产生什么问题,因为以太网的设计本来就是将包发送到整个网络的,然后。只有相应的接收者才接收包,而其他设备则会忽略这个包
在这之后将相应包写入MAC地址表中
第九步 进入路由器
是具有IP和MAC地址的
查看接受的包MAC是不是给自己的,如果是给自己的就放到缓冲区,如果不是则丢弃。
完成包接收操作之后,路由器就会去掉包开头的 MAC 头部。 MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此,当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 头部就会被丢弃。
路由器会根据 MAC 头部后方的 IP 头部中的内容进行包的转发操作
首先,我们需要根据路由表的网关列判断对方的地址。
如果网关是一个 IP 地址,则这个IP地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头里的目标地址了,说明已抵达终点。
根据上面两个之一的IP,根据ARP获取对应的MAC地址,重新封装在头部
第十步拆包
第十一步 发送完数据吗,断开连接进行四次挥手
当被动关闭方在TCP 挥手过程中,「没有数据要发送」并且「开启了TCP 延迟确认机制」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手
接收方不会立即对每个接收到的数据包发送确认(ACK),而是等待一段时间或直到收集到一定数量的数据包后,再统一发送确认。这样做的主要目的是提高网络或系统的效率。
缺点
增加了延迟:
潜在的拥塞问题:
在网络拥塞的情况下,延迟确认可能会进一步加剧问题。例如,在TCP中,发送方可能因为没有及时收到确认而减缓发送速度,这在高延迟网络中可能导致性能问题。
影响拥塞控制和流量控制:
TCP的拥塞控制和流量控制机制依赖于及时的ACK信号。延迟确认可能会干扰这些控制机制的正常工作,导致不稳定的网络性能。
2.3 Linux收发网络包
网卡接受网络包之后,会通过DMA技术,直接将网络包写入到对应内存,也就是写到Ring Buffer里面,一个环形缓冲区,并告诉操作系统包已到达。
接收数据包
在Linux2.6版本以前是采用中断
引入NAPI 机制,2.6版本以后采用中断+轮询
检测数据包到达
中断+轮询
它是混合「中断和轮询」的方式来接收网络包,不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据。
网络包写入内存后发起硬件中断
告诉网卡以后可以直接将数据包写入内存
发起软中断
轮询处理数据
将一个网络包交给网络协议栈逐层处理
会先进入到网络接口层,在这一层会检查报文的合法性,如果不合法则丢弃,合法则会找出该网络包的上层协议的类型,比如是 IPv4,还是 IPv6,接着再去掉帧头和帧尾,然后交给网络层。
到了网络层,则取出 IP 包,判断网络包下一步的走向,比如是交给上层处理还是转发出去。当确认这个网络包要发送给本机后,就会从 IP 头里看看上一层协议的类型是 TCP 还是 UDP,接着去掉 IP 头,然后交给传输层。
传输层取出 TCP 头或 UDP 头,根据四元组「源 IP、源端口、目的 IP、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区。
最后,应用层程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。
发送数据包
应用程序调用Socket接口,陷入内核态
将数据拷贝sk_buff中,并加入到发送缓冲区中
网络协议栈从Socket发送缓冲区中取出sk_buff,开始封装数据
如果使用的是TCP的话,会拷贝一个sk_buff副本,网卡发送完,释放掉内存,如果没收到ACK之前,sk_buff是不会删除的。收到了ACK才会释放掉这个sk_buff
发送数据包涉及的内存拷贝操作
第一次,调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。
第二次,在使用 TCP 传输协议的情况下,从传输层进入网络层的时候,每一个 sk_buff 都会被克隆一个新的副本出来。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,目的是为了实现 TCP 的可靠传输,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff 。
第三次,当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff,并将原来的 sk_buff 拷贝为多个小的 sk_buff。
3.1 HTTP常见面试题
HTTP是超文本传输协议
HTTP 协议是一个双向协议。
为什么用TCP作为协议
可靠性:TCP提供了可靠的传输服务。
错误检测和纠正:TCP通过检验和、序列号、确认响应以及重传机制等来检测和纠正数据在传输过程中的错误。
流量控制和拥塞控制:TCP通过窗口调整和拥塞控制算法来管理数据传输速率,防止网络拥堵和数据丢失。
顺序控制:TCP保证了数据包的顺序,确保数据包按照发送顺序到达和处理。
建立连接的机制:TCP提供了一种可靠的连接建立和终止机制,确保通信双方在开始传输数据前已经建立了稳定的连接,并且在通信结束后能够正确地关闭连接。
状态码
1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx 类状态码表示服务器成功处理了客户端的请求
「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
「206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。
3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。
301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
4xx 类状态码客户端发送的报文有误
「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx 类状态码服务器处理时内部发生了错误
「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思
504 timeout
HTTP常见字段
HOST字段表示服务器域名
Accept开头的是请求的内容
Accept 字段声明自己可以接受哪些数据格式。
Accept-Encoding 字段说明自己可以接受哪些压缩方法。
Content开头的是服务器返回内容
为了解决TCP字节流粘包的问题
TTP 协议通过设置回车符、换行符作为 HTTP header 的边界
通过 Content-Length 字段作为 HTTP body 的边界,
Content-Length 字段,表明本次回应的数据长度
Content-Type字段用于服务器回应时,告诉客户端,本次数据是什么格式。
Content-Encoding 字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式
Connection 字段最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用。
GET和POST的区别
GET 的语义是从服务器获取指定的资源
安全且幂等的
GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求)
RFC 规范并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。只是因为 RFC 规范定义的 GET 请求是获取资源,所以根据这个语义不需要用到 body。
POST 的语义是根据请求负荷(报文body)对指定的资源做出处理
不安全且不幂等的
在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
HTTP的缓存策略
强制缓存
只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。
缓存有效期
Cache-Control, 是一个相对时间;
Expires,是一个绝对时间;
Cache-Control 的优先级高于 Expires 。
浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
协商缓存
协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。
第一种:请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现
请求头部中的 If-Modified-Since:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。
响应头部中的 Last-Modified:标示这个响应资源的最后修改时间;
第二种:请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段。
请求头部中的 If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。
响应头部中 Etag:唯一标识响应资源;
Etag的优先级会高于Last-Modified
协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。
HTTP的特点
无连接:每次请求都要建立连接,需要使用 keep-alive 参数建立长连接、HTTP1.1默认长连接keep-alive
支持使用管道解决队头阻塞
队头阻塞(head of line blocking),由于HTTP1.0规定下一个请求必须在前一个请求响应到达之前才能发送,假设前一个请求响应一直不到达,那么下一个请求就不发送,后面的请求就阻塞了
允许响应数据分块(chunked),即响应的时候不标明Content-Length,客户端就无法断开连接,直到收到服务端的 EOF ,利于传输大文件。
默认是协商缓存
HTTP1.1的优点
简单
灵活和易于扩展
应用广泛和跨平台
HTTP1.1缺点
无状态
使用cookie和session解决
HTTP发送一个请求给服务器,服务器先创建一个session,并在响应报文加入一个Set-cookie的头部,将cookie传给客户端。客户端浏览器会存储这个cookie,并在随后对同一服务器的所有请求中发送它。当服务端再次接受到这个cookie,对比cookie里面的session标识符。让服务端来进行session的匹配。
不安全
监听
混合加密传输
在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。
冒充
将客户端的公钥替换成黑客的公钥,每次发送黑客就可以用自己的私钥发送
将服务器公钥放入到数字证书中,解决了冒充的风险。
CA(证书权威机构)申请数字证书
篡改
摘要算法的方式来实现完整
内容+hash值
但是并不能保证「内容 + 哈希值」不会被中间人替换,因为这里缺少对客户端收到的消息是否来源于服务端的证明。
通过「私钥加密,公钥解密」的方式,来确认消息的身份,我们常说的数字签名算法,就是用的是这种方式,不过私钥加密内容不是内容本身,而是对内容的哈希值加密。
公钥加密,私钥解密
这个目的是为了 保证内容传输的安全 ,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容;
私钥加密,公钥解密
这个目的是为了 保证消息不会被冒充 ,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。
HTTP/1.1 的性能
长连接
管道传输
可以解决请求队头的阻塞
服务器必须按照接收请求的顺序发送对这些管道化请求的响应。
无法解决响应队头的阻塞
队头阻塞
因为引入了链接复用
所以一个TCP连接上复用多个HTTP请求和响应
并且串行化
主要是以前前面一个请求没处理完,其他无依赖的请求就不能被继续处理
HTTP和HTTPS的区别
安全性
HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
解决问题
窃听
冒充
篡改
建立过程
HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的
端口不同
两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。
HTTPS的建立过程
SSL/TLS 协议基本流程
客户端向服务器索要并验证服务器的公钥。
双方协商生产「会话秘钥」。
双方采用「会话秘钥」进行加密通信。
四次通信
RSA加密的示意图
1. ClientHello
首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。
在这一步,客户端主要向服务器发送以下信息:
(1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。
(2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。
(3)客户端支持的密码套件列表,如 RSA 加密算法。
发起通信请求,附带TLS版本号和随机数(用于生成会话密钥),还有加密的信息
2. SeverHello
服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:
(1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。
(2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。
(3)确认的密码套件列表,如 RSA 加密算法。
(4)服务器的数字证书。
服务器返回响应,确认是否支持客户端的TLS版本号和随机数(用于生成会话密钥),并附带服务器的数字证书(经过CA加密)和加密的相关信息,包括服务器支持的密码套件。
为了传递服务端的公钥
3.客户端回应
客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。
如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:
(1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。
(2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。
上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。
服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。
服务器将公钥传递给客户端,客户端验证数字证书的真实性,并使用该公钥生成会话密钥。然后,客户端使用公钥加密这个会话密钥。
获取公钥,生成会话密钥使用公钥进行加密
4. 服务器的最后回应
服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。
然后,向客户端发送最后的信息:
(1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
客户端与服务器使用各自的私钥解密出会话密钥,并接下来开始使用对称加密算法进行数据传输。
私钥解密会话密钥
客户端校验数字证书的流程是怎样的?
示意图
CA是内置在内置在操作系统、浏览器或设备的信任存储中。用户和系统默认信任这些根证书。
1. 信任链 :当一个服务器向客户端(例如浏览器)提供它的证书时,这个证书通常是由一个中间CA签发的,而这个中间CA的证书又可能是由根CA签发的。客户端通过验证这个“链条”来建立信任,从服务器的证书一直追溯到根证书。
2. 与CA的通信::当服务器与CA进行HTTPS通信(例如获取或更新证书)时,它们使用的是CA的证书,这个证书通常也是通过信任链追溯到某个根CA。由于操作系统或浏览器已经内置了对这些根CA的信任,所以可以安全地建立连接,而不会陷入死循环。
CA 签发证书的过程,如上图左边部分:
首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
最后将 Certificate Signature 添加在文件证书上,形成数字证书;
客户端校验服务端的数字证书的过程,如上图右边部分:
首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
哈希运算
通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;
公钥解密
最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。
对称加密和非对称加密
为什么非对称加密会比对称加密更慢
算法复杂性: 非对称加密(如RSA、ECC)依赖于数学上更复杂的原理,如大数因子分解或椭圆曲线数学。这些运算相比于对称加密算法(如AES)使用的运算要复杂得多。
密钥长度: 为了达到相同的安全水平,非对称加密算法通常需要更长的密钥。例如,一个安全的RSA加密可能需要2048位或更长的密钥,而对称加密如AES则可能只需256位密钥。长密钥导致加解密过程需要更多的计算资源。
HTTPS目前是一定安全的
即使你成功进行中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者被恶意导入伪造的根证书),并不是 HTTPS 不够安全。
中间人服务器与客户端在 TLS 握手过程中,实际上发送了自己伪造的证书给浏览器,而这个伪造的证书是能被浏览器(客户端)识别出是非法的,于是就会提醒用户该证书存在问题。
中间人是无法找CA进行签署的,因为证书颁发机构在签发证书前会进行严格的身份验证和域名控制权检查
B/S和C/S架构
HTTP/1.1 相比 HTTP/1.0 性能上的改进
使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
HTTP/2 相比 HTTP/1.1 性能上的改进
头部压缩
HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。
这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
二进制格式
HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。直接解析二进制报文,这增加了数据传输的效率。
并发传输
引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。
针对不同的 HTTP 请求用独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream ,也就是 HTTP/2 可以并行交错地发送请求和响应。
服务端并行交错地发送了两个响应: Stream 1 和 Stream 3,这两个 Stream 都是跑在一个 TCP 连接上,客户端收到后,会根据相同的 Stream ID 有序组装成 HTTP 消息。
仍然没有解决队头阻塞
HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。
服务器主动推送资源
客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。
客户端通过 HTTP/1.1 请求从服务器那获取到了 HTML 文件,而 HTML 可能还需要依赖 CSS 来渲染页面,这时客户端还要再发起获取 CSS 文件的请求,需要两次消息往返,在 HTTP/2 中,客户端在访问 HTML 时,服务器可以直接主动推送 CSS 文件,减少了消息传递的次数。
HTTP/3 做了哪些优化?
无队头阻塞
当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。
更快的连接建立
HTTP/3 在传输数据前虽然需要 QUIC 协议握手,但是这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的。
在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。
连接迁移
当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接。而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。
通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。
QUIC协议
将TCP和UDP的特性互相结合起来,让这个协议既可以保证可靠性,又可以保证实时性,这也就是我们所说的RUDP
HTTP一样同样是应用层协议
为什么高效呢?是因为其基于无连接的UDP而不是基于TCP去实现的。
为什么可靠呢?因为其模仿TCP协议的可靠性,在应用层上做了可靠性的保证。
特点
0RTT 建立链接
TCP的链接有1RTT
HTTPS有3RTT
这里得先说一下QUIC的0RTT并不是完全的0RTT,他同样需要1RTT去做一次秘钥协商,在QUIC中使用的是Diffie-Hellman密钥交换,该算法是一种建立密钥的方法,并非加密方法,但其产生的密钥可用于加密、密钥管理或任何其它的加密方式,这种密钥交换技术的目的在于使两个用户间能安全地交换密钥(KEY)以便用于今后的报文加密
重传机制
在QUIC中序列号都是递增的,并且通过offset来确定在包中的真实位置,这样就可以得到更为准确的RTT。
在TCP中计算RTT的方法就是发出的时间和响应回来的时间相减,但是这样算出的时间不准确,在QUIC中会减去服务端Ack Delay的时间,这样的话就更为精准
粘包/半包
1)粘包与拆包(也称半包)现象:
粘包:指的是在 TCP 传输中,发送方的多个数据包在接收方被合并成一个包接收,导致多条消息数据粘在一起,接收方无法正确区分这些消息的边界。
拆包:指的是发送方的一个数据包在接收方被分成了多个包接收,导致一条完整的消息被拆成多个部分,接收方无法一次性接收到完整的数据。
2)原因:
粘包:主要由于 TCP 是面向字节流的协议,它不关心数据边界,数据在发送方可能被一次性发送,接收方在读取时可能会将多个消息拼接在一起。
拆包:可能由于网络传输中的 MTU(最大传输单元)限制或发送缓冲区大小限制,一个大包被分成了多个小包传输。
3)解决方法:
添加消息分隔符:在每个消息之间添加特定的分隔符(如换行符),接收方可以通过分隔符来区分消息。
使用消息头:在消息的头部添加一个长度字段,指示消息的长度,接收方根据这个长度来读取相应长度的数据。
使用定长消息:每个消息都有固定的长度,接收方按照固定长度读取数据。
3.2 HTTP如何优化
避免发送请求
使用缓存机制
如何减少 HTTP 请求次数?
减少重定向请求次数
定向的工作交由代理服务器完成,就能减少 HTTP 请求次数了
合并请求
把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源还是一样,但是减少请求,也就意味着减少了重复发送的 HTTP 头部。
延迟发送请求
一般 HTML 里会含有很多 HTTP 的 URL,当前不需要的资源,我们没必要也获取过来,于是可以通过「按需获取」的方式,来减少第一时间的 HTTP 请求次数
如何减少 HTTP 响应的数据大小?
无损压缩
有损压缩
3.5 HTTPS如何优化
TLS协议流程
硬件优化
软件优化
协议优化
密钥交换算法优化
RSA 密钥交换算法->ECDHE密钥交换算法
TLS升级
软件升级
证书优化
证书传输优化
证书验证优化
会话复用
对称加密报文的传输优化
4.1 TCP三次挥手与四次挥手
为什么需要 TCP 协议? TCP 工作在哪一层?
IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP 协议来负责
TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
什么是 TCP ?
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
面向连接
一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;
可靠的
无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
字节流
用户消息通过 TCP 协议传输时,消息可能会被操作系统「分组」成多个的 TCP 报文,如果接收方的程序如果不知道「消息的边界」,是无法读出一个有效的用户消息的。并且 TCP 报文是「有序的」,当「前一个」TCP 报文没有收到的时候,即使它先收到了后面的 TCP 报文,那么也不能扔给应用层去处理,同时对「重复」的 TCP 报文会自动丢弃
什么是 TCP 连接
用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。
如何唯一确定一个 TCP 连接呢
TCP 四元组可以唯一的确定一个连接
源地址
源端口
目的地址
目的端口
有一个 IP 的服务端监听了一个端口,它的 TCP 的最大连接数是多少?
对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。
TCP 和 UDP 区别:
1. 连接
TCP 是面向连接的传输层协议,传输数据前先要建立连接。
UDP 是不需要连接,即刻传输数据。
2. 服务对象
TCP 是一对一的两点服务,即一条连接只有两个端点。
UDP 支持一对一、一对多、多对多的交互通信
3. 可靠性
TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按序到达。
UDP 是尽最大努力交付,不保证可靠交付数据。但是我们可以基于 UDP 传输协议实现一个可靠的传输协议,比如 QUIC 协议,具体可以参见这篇文章:
4. 拥塞控制、流量控制
TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
5. 首部开销
TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是20个字节,如果使用了「选项」字段则会变长的。
UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
6. 传输方式
TCP 是流式传输,没有边界,但保证顺序和可靠。
UDP 是一个包一个包的发送,是有边界的,但可能会丢包和乱序。
7. 分片不同
TCP 的数据大小如果大于 MSS 大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装 TCP 数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片。
UDP 的数据大小如果大于 MTU 大小,则会在 IP 层进行分片,目标主机收到后,在 IP 层组装完数据,接着再传给传输层。
TCP 和 UDP 应用场景:
由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:
FTP
HTTP / HTTPS;
由于 UDP 面向无连接,它可以随时发送数据,再加上 UDP 本身的处理既简单又高效
DNS
SNMP
视频、音频等多媒体通信;
广播通信;
TCP三次握手
第三次握手是可以携带数据的,前两次握手是不可以携带数据的
为什么是三次握手
最主要原因就是防止「历史连接」初始化了连接。
如果采用两次握手建立 TCP 连接的场景下,服务端在向客户端发送数据前,并没有阻止掉历史连接,导致服务端建立了一个历史连接,又白白发送了数据,妥妥地浪费了服务端的资源。
要解决这种现象,最好就是在服务端发送数据前,也就是建立连接之前,要阻止掉历史连接,这样就不会造成资源浪费,而要实现这个功能,就需要三次握手。
避免资源浪费
如果只有两次,那么收到一个SYN报文就会建立一个链接,会建立多个冗余链接
「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
第一段或者第二段丢失 第一个syn报文要不断重发,会建立多次链接
那么服务端也不知道到底是哪一个建立链接,无法确认就造成资源浪费和链接不稳定
「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
为什么每次建立 TCP 连接时,初始化的序列号都要求不一样呢?
为了防止历史报文被下一个相同四元组的连接接收(主要方面);
服务器因为异常关闭连接后又打开链接 那么以前网络延迟的报文就会被接收到
为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收;
初始序列号 ISN 是如何随机产生的?
起始 ISN 是基于时钟的,每 4 微秒 + 1,转一圈要 4.55 个小时
ISN = M + F(localhost, localport, remotehost, remoteport)。
M
是一个计时器,这个计时器每隔 4 微秒加 1。
F
是一个 Hash 算法,根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。要保证 Hash 算法不能被外部轻易推算得出,用 MD5 算法是一个比较好的选择。
第一次握手丢失了,会发生什么?
客户端迟迟收不到服务端的 SYN-ACK 报文(第二次握手),就会触发「超时重传」机制,重传 SYN 报文,而且重传的 SYN 报文的序列号都是一样的。
第一次超时重传是在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2 倍。
第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应 ACK,客户端就不再发送 SYN 包,然后断开 TCP 连接。
第二次握手丢失了,会发生什么?
那么客户端就觉得可能自己的 SYN 报文(第一次握手)丢失了,于是客户端就会触发超时重传机制,重传 SYN 报文。
服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传 SYN-ACK 报文。
第三次握手丢失了,会发生什么?
会触发超时重传机制,重传 SYN-ACK 报文,直到收到第三次握手,或者达到最大重传次数。
什么是 SYN 攻击?如何避免 SYN 攻击?
半连接队列,也称 SYN 队列;
全连接队列,也称 accept 队列;
当服务端接收到客户端的 SYN 报文时,会创建一个半连接的对象,然后将其加入到内核的「 SYN 队列」;
接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;
服务端接收到 ACK 报文后,从「 SYN 队列」取出一个半连接对象,然后创建一个新的连接对象放入到「 Accept 队列」;
应用通过调用 accpet() socket 接口,从「 Accept 队列」取出连接对象。
SYN 攻击方式
当 TCP 半连接队列满了,后续再在收到 SYN 报文就会丢弃,导致客户端无法和服务端建立连接。
解决方法
控制该队列的接受速度
增大队列
减少SYN+ACK重传次数
开启 syncookies 功能
当 「 SYN 队列」满之后,后续服务端收到 SYN 包,不会丢弃,而是根据算法,计算出一个 cookie 值;
将 cookie 值放到第二次握手报文的「序列号」里,然后服务端回第二次握手给客户端;
服务端接收到客户端的应答报文时,服务端会检查这个 ACK 包的合法性。如果合法,将该连接对象放入到「 Accept 队列」。
最后应用程序通过调用 accpet() 接口,从「 Accept 队列」取出的连接。
四次挥手
客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT 状态。
客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。
客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。
第一次挥手丢失
当客户端(主动关闭方)调用 close 函数后,就会向服务端发送 FIN 报文,试图与服务端断开连接,此时客户端的连接进入到 FIN_WAIT_1 状态。
正常情况下,如果能及时收到服务端(被动关闭方)的 ACK,则会很快变为 FIN_WAIT2状态。
如果第一次挥手丢失了,那么客户端迟迟收不到被动方的 ACK 的话,也就会触发超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数控制。
当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,则会在等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到第二次挥手,那么直接进入到 close 状态。
第二次挥手丢失
当服务端收到客户端的第一次挥手后,就会先回一个 ACK 确认报文,此时服务端的连接进入到 CLOSE_WAIT 状态。
在前面我们也提了,ACK 报文是不会重传的,所以如果服务端的第二次挥手丢失了,客户端就会触发超时重传机制,重传 FIN 报文,直到收到服务端的第二次挥手,或者达到最大的重传次数。
第三次挥手丢失了
当服务端重传第三次挥手报文的次数达到了 3 次后,由于 tcp_orphan_retries 为 3,达到了重传最大次数,于是再等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到客户端的第四次挥手(ACK报文),那么服务端就会断开连接。
客户端因为是通过 close 函数关闭连接的,处于 FIN_WAIT_2 状态是有时长限制的,如果 tcp_fin_timeout 时间内还是没能收到服务端的第三次挥手(FIN 报文),那么客户端就会断开连接
第四次挥手丢失了
当服务端重传第三次挥手报文达到 2 时,由于 tcp_orphan_retries 为 2, 达到了最大重传次数,于是再等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到客户端的第四次挥手(ACK 报文),那么服务端就会断开连接。
客户端在收到第三次挥手后,就会进入 TIME_WAIT 状态,开启时长为 2MSL 的定时器,如果途中再次收到第三次挥手(FIN 报文)后,就会重置定时器,当等待 2MSL 时长后,客户端就会断开连接。
为什么 TIME_WAIT 等待的时间是 2MSL
MSL 是 Maximum Segment Lifetime,报文最大生存时间
因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。
MSL 应该要大于等于 TTL 消耗为 0 的时间
一来一回需要等待 2 倍的时间
为什么需要 TIME_WAIT 状态?
防止历史连接中的数据,被后面相同四元组的连接错误的接收;
服务端在关闭连接之前发送的 SEQ = 301 报文,被网络延迟了。
接着,服务端以相同的四元组重新打开了新连接,前面被延迟的 SEQ = 301 这时抵达了客户端,而且该数据报文的序列号刚好在客户端接收窗口内,因此客户端会正常接收这个数据报文,但是这个数据报文是上一个连接残留下来的,这样就产生数据错乱等严重的问题。
确保最后一个ACK报文被接收到了
保证「被动关闭连接」的一方,能被正确的关闭;
等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。
TIME_WAIT 过多有什么危害
第一是占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等;
如果服务端(主动发起关闭连接方)的 TIME_WAIT 状态过多,并不会导致端口资源受限,因为服务端只监听一个端口,而且由于一个四元组唯一确定一个 TCP 连接,因此理论上服务端可以建立很多连接,但是 TCP 连接过多,会占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等。
第二是占用端口资源,端口资源也是有限的
如果客户端(主动发起关闭连接方)的 TIME_WAIT 状态过多,占满了所有端口资源,那么就无法对「目的 IP+ 目的 PORT」都一样的服务端发起连接了,
服务器出现大量 TIME_WAIT 状态的原因有哪些
第一个场景:HTTP 没有使用长连接
建立长连接
Connection: Keep-Alive
从 HTTP/1.1 开始, 就默认是开启了 Keep-Alive,
只要客户端和服务端任意一方的 HTTP header 中有 Connection:close 信息,那么就无法使用 HTTP 长连接的机制。
不管哪一方禁用了 HTTP Keep-Alive,都是由服务端主动关闭连接
所以此时就会造成服务器大量Time_wait
第二个场景:HTTP 长连接超时
服务器主动申请关闭连接
第三个场景:HTTP 长连接的请求数量达到上限
服务器出现大量 CLOSE_WAIT 状态的原因有哪些?
CLOSE_WAIT无法转化为FIN_ACK,也就是无法发送FIN包
服务端出现大量 CLOSE_WAIT 状态的连接的时候,通常都是代码的问题,这时候我们需要针对具体的代码一步一步的进行排查和定位,主要分析的方向就是服务端为什么没有调用 close
如果已经建立了连接,但是客户端突然出现故障了怎么办
TCP 搞了个保活机制
tcp_keepalive_time=7200:表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制
tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
tcp_keepalive_probes=9:表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。
也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。
TCP保活机制的几种情况
第一种,对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
第二种,对端主机宕机并重启。当 TCP 保活的探测报文发送给对端后,对端是可以响应的,但由于没有该连接的有效信息,会产生一个 RST 报文,这样很快就会发现 TCP 连接已经被重置。
第三种,是对端主机宕机(注意不是进程崩溃,进程崩溃后操作系统在回收进程资源的时候,会发送 FIN 报文,而主机宕机则是无法感知的,所以需要 TCP 保活机制来探测对方是不是发生了主机宕机),或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。
如果已经建立了连接,但是服务端的进程崩溃会发生什么?
当服务端的进程崩溃后,内核需要回收该进程的所有 TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成
4.2 重传,拥塞控制,流量控制
重传
超时重传
以时间为驱动
快速重传
以数据驱动重传
第一份 Seq1 先送到了,于是就 Ack 回 2;
结果 Seq2 因为某些原因没收到,Seq3 到达了,于是还是 Ack 回 2;
后面的 Seq4 和 Seq5 都到了,但还是 Ack 回 2,因为 Seq2 还是没有收到;
发送端收到了三个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2。
最后,收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。
是它依然面临着另外一个问题重传的时候,是重传一个,还是重传所有的问题。
如果只选择重传 Seq2 一个报文,那么重传的效率很低。因为对于丢失的 Seq3 报文,还得在后续收到三个重复的 ACK3 才能触发重传。
如果选择重传 Seq2 之后已发送的所有报文,虽然能同时重传已丢失的 Seq2 和 Seq3 报文,但是 Seq4、Seq5、Seq6 的报文是已经被接收过了,对于重传 Seq4 ~Seq6 折部分数据相当于做了一次无用功,浪费资源。
SACK
在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
中间某个报文丢失了
ACK号小于已经接收到的SACK号
通过ACK和Sack来确定已经收到的报文, Ack-Sack-1 就是丢失报文
Duplicate SACK
「接收方」发给「发送方」的两个 ACK 确认应答都丢失了,所以发送方超时后,重传第一个数据包(3000 ~ 3499)
于是「接收方」发现数据是重复收到的,于是回了一个 SACK = 3000~3500,告诉「发送方」 3000~3500 的数据早已被接收了,因为 ACK 都到了 4000 了,已经意味着 4000 之前的所有数据都已收到,所以这个 SACK 就代表着 D-SACK。
这样「发送方」就知道了,数据没有丢,是「接收方」的 ACK 确认报文丢了
数据包(1000~1499) 被网络延迟了,导致「发送方」没有收到 Ack 1500 的确认报文。
而后面报文到达的三个相同的 ACK 确认报文,就触发了快速重传机制,但是在重传后,被延迟的数据包(1000~1499)又到了「接收方」;
所以「接收方」回了一个 SACK=1000~1500,因为 ACK 已经到了 3000,所以这个 SACK 是 D-SACK,表示收到了重复的包。
这样发送方就知道快速重传触发的原因不是发出去的包丢了,也不是因为回应的 ACK 包丢了,而是因为网络延迟了。
Sack区间小于ACK, 表示我都已经ACK到后面了,不要再发送前面的重复报文给我了
响应报文丢失了
此时SACK号小于ACK号
SACK携带着重复接收的数据序列
滑动窗口
累计确认或者累计应答。
窗口大小
通常窗口的大小是由接收方的窗口大小来决定的。
通过指针来确认这几部分
SND.WND:表示发送窗口的大小(大小是由接收方指定的);
SND.UNA(Send Unacknoleged):是一个绝对指针,它指向的是已发送但未收到确认的第一个字节的序列号,也就是 #2 的第一个字节。
SND.NXT:也是一个绝对指针,它指向未发送但可发送范围的第一个字节的序列号,也就是 #3 的第一个字节。
流量控制
防止接收方处理不过来
流量控制过程
不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况
窗口关闭
致发送方一直等待接收方的非 0 窗口通知,接收方也一直等待发送方的数据,如不采取措施,这种相互等待的过程,会造成了死锁的现象
解决方法
为了解决这个问题,TCP 为每个连接设有一个持续定时器,只要 TCP 连接一方收到对方的零窗口通知,就启动持续计时器。
如果持续计时器超时,就会发送窗口探测 ( Window probe ) 报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。
糊涂窗口综合症
接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾地发送这几个字节,这就是糊涂窗口综合症。
解决方法
让接收方不通告小窗口给发送方
当「窗口大小」小于 min( MSS,缓存空间/2 ) ,也就是小于 MSS 与 1/2 缓存大小中的最小值时,就会向发送方通告窗口为 0,也就阻止了发送方再发数据过来。
等到接收方处理了一些数据后,窗口大小 >= MSS,或者接收方缓存空间有一半可以使用,就可以把窗口打开让发送方发送数据过来。
让发送方避免发送小数据
使用 Nagle 算法,该算法的思路是延时处理,只有满足下面两个条件中的任意一个条件,才可以发送数据:
条件一:要等到窗口大小 >= MSS 并且 数据大小 >= MSS;
条件二:收到之前发送数据的 ack 回包;
拥塞控制
拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。防止网络处理不完
swnd = min(cwnd, rwnd)
发生了超时重传,就会认为网络出现了拥塞。
算法
慢启动
连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。
当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个
当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这一次能够发送 4 个
当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4 个,所以这一次能够发送 8 个。
拥塞避免
慢启动门限 ssthresh (slow start threshold)状态变量。
当 cwnd < ssthresh 时,使用慢启动算法。
当 cwnd >= ssthresh 时,就会使用「拥塞避免算法」。
每当收到一个 ACK 时,cwnd 增加 1/cwnd。
接上前面的慢启动的栗子,现假定 ssthresh 为 8:
当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长。
拥塞发生
超时重传
ssthresh 设为 cwnd/2,
cwnd 重置为 初始值
快速重传
cwnd = cwnd/2 ,也就是设置为原来的一半;
ssthresh = cwnd;
快速恢复
快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕
cwnd = cwnd/2 ,也就是设置为原来的一半;
ssthresh = cwnd;
注意这里是重复收到ACK包 才+1 如果收到不同的ACK立马就变回原来的默认值了
拥塞窗口 cwnd = ssthresh + 3 ( 3 的意思是确认有 3 个数据包被收到了);
重传丢失的数据包;
如果再收到重复的 ACK,那么 cwnd 增加 1;
如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;
Cooike Seesion JWT
JWT
JWT(JSON Web Token)是一种用于在各方之间传递安全信息的紧凑、URL安全的令牌格式。
在用户登录后,服务器生成JWT并返回给客户端。客户端在后续请求中通过HTTP头部(通常是Authorization头)发送该JWT,服务器则验证该JWT的有效性以进行用户身份验证。
因为它的无状态性,常用于分布式系统和微服务架构中。
其结构主要包括三个部分:Header、Payload和Signature。
1)Header:描述令牌的元数据,通常包含令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256)。
2)Payload:包含声明(Claims),即传递的数据。这些数据通常包括用户信息和其他相关数据。常见的声明类型有iss(发行者)、exp(到期时间)、sub(主题)等。
3)Signature:将Header和Payload用指定的算法进行签名,用以验证JWT的真实性和完整性。签名确保了令牌内容在传输过程中未被篡改。
JWT的优点:
自包含:JWT中包含了所有必要的信息,因此在验证时不需要查询数据库,提升了性能。
跨语言:由于JWT是基于JSON的,几乎所有编程语言都支持它的生成和解析。
废弃
使用黑名单
版本控制
5.1 IP基础知识
IP分类
主机个数 = 2^主机号长度-2
当主机号部分全为0时,表示该IP地址为网络地址(Network Address)
全部为1表示 广播地址
广播给所有的主机
无分类地址 CIDR
比如 10.100.122.2/24,这种地址表示形式就是 CIDR,/24 表示前 24 位是网络号,剩余的 8 位是主机号。
IPV6
IPV4
32位
V6
128位
子网划分
IP相关协议
DNS域名解析
ARP
IP找到对应MAC
免费ARP
用来通知网络中的设备某个IP地址的MAC地址映射发生变化
防止IP冲突,因为IP可以手动设置,MAC设备是物理标识,发送免费ARP防止不同mac映射一个IP
ARP代理
用于不同子网设备直接通信,网络设备代表其他设备响应ARP请求
普通机器发送时候,先经过ARP代理,被抢先应答
DHCP
从DHCP服务器动态获取IP
NAT
内网IP转为外网IP
NPAT
可以把 IP 地址 + 端口号一起进行转换。
ICMP
确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。
互联网控制报文协议
查询报文类型
差错报文类型
IGMP
组播路由协议
常规询问
离开组播
情况一, 组播里面还有设备
情况二 组播里面没有设备了
RPC
远程过程调用
RPC不是指跨物理机器的调用,而是指多个进程或者多个计算机不同进程间的调用
RPC框架
符合从远程计算机获取服务而不需要了解代码的网络技术实现的一种协议的框架称为RPC框架
一般现在都是以TCP协议作为底层的传输协议
强调的是过程调用,调用过程对用户完全透明
RPC框架就是为了解决分布式网络之间的网络通信问题
RPC协议
四个组件
Client客户端表示服务的调用方;
Sever服务端是真正的服务提供方;
Client Stub表示客户端存根,专门用来存放服务端的地址信息,再将客户端的请求参数打包成网络消息,也就是序列化,然后通过网络远程发送给服务提供方。
Server Stub表示服务端存根,用来接收客户端发送过来的消息,然后,解析消息内容,也就是反序列化,并且调用本地方法。
应用场景
分布式系统网络通讯
分布式子系统之间的服务治理
分布式负载均衡和流控
服务发现与注册
构建分布式调试环境
ping命令
ping的通但是登录不进去
网络策略或防火墙规则:
网络防火墙可能配置为允许 ICMP(用于 ping 命令)通信,但阻止了其他类型的网络连接,如 SSH(端口 22)或 RDP(端口 3389)。
服务未运行:
目标机器上你试图连接的服务(例如 SSH、FTP、RDP 等)可能没有运行,或者配置错误,因此无法接受连接。
认证问题:
可能是凭据问题,如密码错误、账号锁定、秘钥不匹配等。
如果是 SSH,还可能是因为 sshd_config 配置文件限制了某些用户或 IP 地址的访问。
端口未开放:
尽管目标机器正在运行,但你尝试登录的特定端口可能没有在网络防火墙中开放。
资源限制:
目标机器上可能存在连接数限制或资源耗尽(如内存、CPU过载),导致无法处理新的登录请求。
协议版本或加密问题:
特别是 SSH,如果客户端和服务器之间的协议版本或加密算法不兼容,也可能导致连接失败。
使用的是ICMP报文协议
只有IP或者MAC地址能否完成通讯
在以太网中只通过交换机的话应该只要MAC地址就能通讯了