个人学习笔记,仅供参考!
OSI参考模型
这一模型将通信协议中必要的功能分成了7层,该模型中,每个分层都接收由它下一层所提供的特定服务,并且负责为自己的上一层提供特定的服务。上下层之间进行交互时所遵循的约定叫做“接口”。同一层之间的交互所遵循的约定叫做“协议”。
应用层:为应用程序提供服务并规定应用程序中通信相关的细节
表示层:将应用处理的信息转换为适合网络传输的格式,或将来自下一层的数据转换为上层能够处理的格式。因此它主要负责数据格式的转换以及基本压缩加密。
会话层:负责建立和断开通信连接(数据流动的逻辑通路),以及数据的分割等数据传输相关的管理,决定采用何种连接方法是会话层的主要责任。会话层只对何时建立连接、何时发送数据等问题进行管理,并不具有实际传输数据的功能。
传输层:起着可靠传输的作用。只在通信双方节点上进行处理,而无需在路由器上处理。会话层负责决定建立连接和断开连接的时机,而传输层进行实际的建立和断开处理。在两个主机之间创建逻辑上的通信连接即是传输层的主要作用 。
网络层:主要负责寻址和路由选择,在网络互连的环境中,将数据发送到接收端主机 。
数据链路层 :负责物理层面上相邻节点之间的数据传输及数据处理。通信传输实际上是通过物理的传输介质实现的。
物理层:负责底层数据传输,利用传输介质为数据链路层提供支持,实现相邻计算机节点之间比特流的透明传输。
OSI七层模型是一个标准,而非实现,TCP/IP四层模型是一个实现的应用模型
分层可以将每个分层独立使用,即使系统中某些分层发生变化,也不会波及整个系统。因此,可以构造一个扩展性和灵活性都较强的系统。此外,通过分层能够细分通信功能,更易于实现每个分层的协议,并界定各个分层的具体责任和义务。这些都属于分层的优点
TCP/IP四层模型
应用层:应用层位于传输层之上,主要提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给下一层传输层来传输。 我们把应用层交互的数据单元称为报文。
传输层:传输层的主要任务就是负责向两台终端设备进程之间的通信提供通用的数据传输服务
。 应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。
传输层主要使用两种协议:
1、TCP协议(传输控制协议):提供面向连接基于字节流的可靠的数据传输服务,其数据传输的单位为报文段。
2、UDP协议(用户数据报协议):提供无连接的基于数据报的尽最大努力交付的数据传输服务,其数据传输单位为用户数据报
网络层:网络层负责为分组交换网上的不同主机提供通信服务。 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报。
网际接口层
以把网络接口层看作是数据链路层和物理层的合体。
-
数据链路层。数据链路层的作用是将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。
-
物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异
网络通信方式大致分为两种——电路交换和分组交换 。在电路交换中,交换机主要负责数据的中转处理。 电路交换中,于一台计算机在收发信息时会独占整个电路,其他计算机只能 等待这台计算机处理结束以后才有机会使用这条电路收发数据。并且在此过程中,谁也无法预测某一台计算机的数据传输从何时开始又在何时结束。人们想到了一个新的方法,即让连接到通信电路的计算机将所要发送的数据分成多个数据包,按照一定的顺序排列之后分别发送。这就是分组交换。有了分组交换,数据被细分后,所有的计算机就可以一齐收发数据,这样也就提高了通信线路的利用率。
分组交换的大致处理过程是:发送端计算机将数据分组发送给路由器,路由器收到这些分组数据以后,缓存到自己的缓冲区,然后再转发给目标计算机。因此,分组交换也有另一个名称:蓄积交换。
任播是指在特定的多台主机中选出一台作为接收端的一种通信方式。 所被选中的那 台特定主机将返回一个单播信号,随后发送端主机会只跟这台主机进行通信。任播在实际网络中的应用有DNS根域名解析服务器 。
IP地址分层。IP地址由网络号和主机号两部分组成。
Mac寻址参考的是地址转发表,而ip寻址参考的是路由控制表。地址转发表根据自学自动生成。路由控制表则根据路由协议自动生成。
发送方将数据发送给路由器,路由器查询路由控制表将数据发送给下一跳路由器,经过不停的转发,最后,路由器将数据发送给交换机,交换机查询地址转换表将数据发送给目标主机。
私有IP地址
私有地址分3类:
A类:第一段为10的都是私有地址 10.0.0.1 --- 10.255.255.254 10.0.0.0表示整个网段,10.255.255.255是广播地址
B类:以172.16 172.31 ---开头的都是私有地址 172.16.0.1 --- 172.31.255.254 172.16.0.0表示整个网段,172.31.255.255是广播地址
Ç类:以192.168开头的都是私有地址 192.168.0.1 --- 192.168.255.254 192.168.0.0表示整个网段,192.168.255.255是广播地址
网卡(网络适配器):使计算机联网的设备
中继器:物理层上延长网络的设备。中继器是对减弱的信号进行放大和发送的设备。由电缆传过来的电信号或光 信号经由中继器的波形调整和放大再传给另一个电缆。一个10Mbps的以太网最多可以用4个中继器分段连接,而一个100Mbps的以太网则最多只能连两个中继器。有些中继器可以提供多个端口服务。这种中继器被称作中继集线器或集线器
网桥/二层交换机:从数据链路层延长网络的设备。
路由器/三层交换机:通过网络层转发分组数据的设备。
4-7层交换机:处理传输层以上各种网络传输的设备。
网关:转换协议的设备。在同一种类型的协议之间转发数据叫做应用网关。
在数据传输的过程中,两个设备之间数据流动的物理速度称为传输速率。单位为bps(每秒比特数)传输速率高也不是指单位数据流动的速度有多快,而是指单位时间内传输的数据量有多少 。传输速率又称作带宽 B。带宽越大网络传输能力就越强。低速数据链路就如同车道较少无法让很多车同时通过的情况。与之 相反,高速数据链路就相当于有多个车道,一次允许更多车辆行驶的道路。
主机之间实际的传输速率被称作吞吐量。
虚拟化技术 它是指当一个网站(也可以是其他系统)需要调整运营所使用的资源时,并不增减服务器、存储设备、网络等实际的物理设备,而是利用软件将这些物理设备虚拟化,在有必要增减资源的时候,通过软件按量增减的一种机制。通过此机制实现按需分配、按比例分配,对外提供可靠的服务。
数据(邮件)发送接收过程:经由应用层、传输层、网络层将每层的首部信息加到数据头部,然后将IP数据包发送给网络接口(以太网驱动)进行处理,添加上源MAC地址和目标MAC地址之后,再加上表示上一层协议类型的识别信息,经由物理层发送给接收端。接收端收到以太网包后,查看目标MAC地址,如果不是发给自己的就丢弃,如果是发给自己的就查看以太网首部中的协议类型信息,若是IP协议类型,便将数据发给IP模块处理,若是ARP协议类型,便将数据传给ARP模块进行处理。IP模块收到IP包首部及后面的数据部分以后,也做类似的处理 。如果上一层是TCP就将IP包首部之后的部分传给TCP处理;如果是UDP则将IP包首部后面的部分传给UDP处理。在TCP模块中,首先会计算一下校验和,判断数据是否被破坏。然后检查是否在按照序号接收数据。最后检查端口号,确定具体的应用程序。数据接收完毕后,接收端则发送一个“确认回执”给发送端。如果这个回执信息未能达到发送端,那么发 送端会认为接收端没有接收到数据而一直反复发送。 数据被完整地接收以后,会传给由端口号识别的应用程序。(图解TCP/IP94页)
网络拓扑包括总线型、环型、星型、网状型等
MAC地址用于识别数据链路中互连的节点 ,MAC地址长48比特 ,一般使用十六进制表示,在使用网卡(NIC)的情况下,MAC地址一般会被烧入到ROM 中,MAC地址的第1位表示单播或者多播,为0是单播,,为1是多播,第二位为0表示全局地址,为1表示本地地址。
即使MAC地址相同,只要不是同属一个数据链路就不会出现问题。
从通信介质(通信,介质)的使用方法上看,网络可分为共享介质型和非共享介质型
共享介质型网络指由多个设备共享一个通信介质的一种网络。最早的以太网和FDDI就是介质共享型网
络。在这种方式下,设备之间使用同一个载波信道进行发送和接收。为此,基本上采用半双工通信方式,并有必要对介质进行访问控制。共享介质型网络中有两种介质访问控制方式:一种是争用方式,另一种是令牌传递方式
1、TCP基本知识
TCP头格式:
序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。
控制位:
ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定。FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。
2、为什么需要 TCP 协议? TCP 工作在哪一层?
IP
层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。
如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP
协议来负责。
因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
3、什么是 TCP ?
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
面向连接:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;
可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当「前一个」消息没有收到的时候,即使它先收到了后面的字节,那么也不能扔给应用层去处理,同时对「重复」的报文会自动丢弃。
所谓面向字节流的协议是说当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。
4、如何唯一确定一个 TCP 连接呢?
TCP 四元组可以唯一的确定一个连接,四元组包括如下:
-
源地址
-
源端口
-
目的地址
-
目的端口
源地址和目的地址的字段(32位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。
源端口和目的端口的字段(16位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程。
5、有一个 IP 的服务器监听了一个端口,它的 TCP 的最大连接数是多少?
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。
对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。
当然,服务端最大并发 TCP 连接数远不能达到理论上限,会受以下因素影响:
文件描述符限制,每个 TCP 连接都是一个文件,如果文件描述符被占满了,会发生 too many open files。Linux 对可打开的文件描述符的数量分别作了三个方面的限制:系统级:当前系统可打开的最大数量,通过 cat /proc/sys/fs/file-max 查看;用户级:指定用户可打开的最大数量,通过 cat /etc/security/limits.conf 查看;进程级:单个进程可打开的最大数量,通过 cat /proc/sys/fs/nr_open 查看;内存限制,每个 TCP 连接都要占用一定内存,操作系统的内存是有限的,如果内存资源被占满后,会发生 OOM。
6、UDP 和 TCP 有什么区别呢?分别的应用场景是?
UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务。
UDP 协议非常简单,头部只有 8
个字节( 64 位)
-
目标和源端口:主要是告诉 UDP 协议应该把报文发给哪个进程。各16位
-
包长度:该字段保存了 UDP 首部的长度跟数据的长度之和。16位
-
校验和:校验和是为了提供可靠的 UDP 首部和数据而设计,防止收到在网络传输中受损的 UDP包。16位
TCP 和 UDP 区别:
-
连接
TCP 是面向连接的传输层协议,传输数据前先要建立连接。UDP 是不需要连接,即刻传输数据。
-
服务对象
TCP 是一对一的两点服务,即一条连接只有两个端点。UDP 支持一对一、一对多、多对多的交互通信
-
可靠性
TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按序到达。UDP 是尽最大努力交付,不保证可靠交付数据。
-
拥塞控制、流量控制
TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
-
首部开销
TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长的。UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
-
传输方式
TCP 是流式传输,没有边界,但保证顺序和可靠。UDP 是一个包一个包的发送,是有边界的,但可能会丢包和乱序。
-
分片不同
TCP 的数据大小如果大于 MSS 大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装 TCP 数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片。UDP 的数据大小如果大于 MTU 大小,则会在 IP 层进行分片,目标主机收到后,在 IP 层组装完数据,接着再传给传输层。TCP 和 UDP 应用场景:
由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:
-
FTP 文件传输;
-
HTTP / HTTPS;
由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:
-
包总量较少的通信,如 DNS 、SNMP 等;
-
视频、音频等多媒体通信;
-
广播通信;
7、TCP报文的长度在TCP三次握手中那一次确定的?
TCP会将应用层交付下来的数据分为TCP认为最适合发送的数据块。这里的数据块大小就是MSS(maximum segment size最大分段长度)。MSS字段位于TCP首部中的选项字段。
MSS的值是在TCP三次握手建立连接的过程中,经通信双方协商确定的 。链路层使用以太网的话,IP层的MTU是1500 byte,这样去掉IP数据报首部(20 byte),在去掉TCP首部(20 byte)后为1460 byte,此时在默认情况下TCP“选项”字段的MSS值为1460 byte = 1500 - 20 - 20。
面我们详细说明MSS值的确定过程。
MSS值只会出现在SYN报文中,即SYN=1时,才会有MSS字段值。当客户端想要以TCP方式从服务器端下载数据时,
(1)首先客户端会发送一个SYN请求报文,这个SYN报文的“选项”字段中会有MSS值(MSS = MTU- IP首部长度 - TCP首部长度)。该MSS值是为了告知对方最大的发送数据大小。
(2)当服务器端收到SYN报文后,会向请求端返回SYN+ACK(同步确认报文)报文,其中的“选项”字段也会有MSS值。
(3)通信双方选择SYN和SYN+ACK报文中最小的MSS最为此次TCP连接的MSS,从而达到通信双发协商MSS的效果。
综上,可以回答开始时的问题。在第二次握手后就可以确定TCP中最大传输报文(MSS)大小。
8、为什么 UDP 头部没有「首部长度」字段,而 TCP 头部有「首部长度」字段呢?
原因是 TCP 有可变长的「选项」字段,而 UDP 头部长度则是不会变化的,无需多一个字段去记录 UDP 的首部长度。
9、为什么 UDP 头部有「包长度」字段,而 TCP 头部则没有「包长度」字段呢?
因为为了网络设备硬件设计和处理方便,首部长度需要是 4 字节的整数倍。
如果去掉 UDP 「包长度」字段,那 UDP 首部长度就不是 4 字节的整数倍了,所以小林觉得这可能是为了补全 UDP 首部长度是 4 字节的整数倍,才补充了「包长度」字段。
10、简述TCP 三次握手过程和状态变迁
TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。
-
一开始,客户端和服务端都处于
CLOSED
状态。先是服务端主动监听某个端口,处于LISTEN
状态 -
客户端会随机初始化序号(
client_isn
),将此序号置于 TCP 首部的「序号」字段中,同时把SYN
标志位置为1
,表示SYN
报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN-SENT
状态。 -
服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
-
客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。
-
服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态。
从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的
11、如何在 Linux 系统中查看 TCP 状态?
TCP 的连接状态查看,在 Linux 可以通过 netstat -napt
命令查看
12、为什么是三次握手?不是两次、四次?
三个方面分析三次握手的原因:
-
三次握手才可以阻止重复历史连接的初始化(主要原因)
-
三次握手才可以同步双方的初始序列号
-
三次握手才可以避免资源浪费
原因一:避免历史连接
简单来说,三次握手的首要原因是为了防止旧的重复连接初始化造成混乱。
考虑一个场景,客户端先发送了 SYN(seq = 90) 报文,但是被网络阻塞了,服务端并没有收到,接着客户端又重新发送了 SYN(seq = 100) 报文,注意不是重传 SYN,重传的 SYN 的序列号是一样的,来看看三次握手是如何阻止历史连接的:
客户端连续发送多次 SYN 建立连接的报文,在网络拥堵情况下:
一个「旧 SYN 报文」比「最新的 SYN 」 报文早到达了服务端;那么此时服务端就会回一个 SYN + ACK 报文给客户端;客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。如果是两次握手连接,就无法阻止历史连接,主要是因为在两次握手的情况下,「被动发起方」没有中间状态给「主动发起方」来阻止历史连接,导致「被动发起方」可能建立一个历史连接,造成资源浪费。
你想想,两次握手的情况下,「被动发起方」在收到 SYN 报文后,就进入 ESTABLISHED 状态,意味着这时可以给对方发送数据给,但是「主动发」起方此时还没有进入 ESTABLISHED 状态,假设这次是历史连接,主动发起方判断到此次连接为历史连接,那么就会回 RST 报文来断开连接,而「被动发起方」在第一次握手的时候就进入 ESTABLISHED 状态,所以它可以发送数据的,但是它并不知道这个是历史连接,它只有在收到 RST 报文后,才会断开连接。
可以看到,上面这种场景下,「被动发起方」在向「主动发起方」发送数据前,并没有阻止掉历史连接,导致「被动发起方」建立了一个历史连接,又白白发送了数据,妥妥地浪费了「被动发起方」的资源。
因此,要解决这种现象,最好就是在「被动发起方」发送数据前,也就是建立连接之前,要阻止掉历史连接,这样就不会造成资源浪费,而要实现这个功能,就需要三次握手。
所以,TCP 使用三次握手建立连接的最主要原因是防止「历史连接」初始化了连接。
原因二:同步双方初始序列号
TCP 协议的通信双方, 都必须维护一个「序列号」, 序列号是可靠传输的一个关键因素,它的作用:
1、接收方可以去除重复的数据;2、接收方可以根据数据包的序列号按序接收;3、可以标识发送出去的数据包中, 哪些是已经被对方收到的(通过 ACK 报文中的序列号知道);
可见,序列号在 TCP 连接中占据着非常重要的作用,所以当客户端发送携带「初始序列号」的 SYN 报文的时候,需要服务端回一个 ACK 应答报文,表示客户端的 SYN 报文已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应,这样一来一回,才能确保双方的初始序列号能被可靠的同步。
四次握手其实也能够可靠的同步双方的初始化序号,但由于第二步和第三步可以优化成一步,所以就成了「三次握手」。
而两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。
原因三:避免资源浪费
如果只有「两次握手」,当客户端的 SYN 请求连接在网络中阻塞,客户端没有接收到 ACK 报文,就会重新发送 SYN ,由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立一个连接,这会造成什么情况呢?
如果客户端的 SYN 阻塞了,重复发送多次 SYN 报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。
小结
TCP 建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。
不使用「两次握手」和「四次握手」的原因:
「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
13、为什么每次建立 TCP 连接时,初始化的序列号都要求不一样呢?
主要原因有两个方面:
1、为了防止历史报文被下一个相同四元组的连接接收(主要方面),如果每次建立连接客户端和服务端的初始化序列号都「不一样」,就有大概率因为历史报文的序列号「不在」对方接收窗口,从而很大程度上避免了历史报文 ,注意是很大程度上,并不是完全避免了 ,最后又引入时间戳的机制,从而完全避免了历史报文被接收的问题。 时间戳机制:每收到一个新数据包都会读取数据包中的时间戳值跟 Recent TSval 值做比较,如果发现收到的数据包中时间戳不是递增的,则表示该数据包是过期的,就会直接丢弃这个数据包。 2、为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收;
14、既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?
MTU:一个网络包的最大长度,以太网中一般为 1500 字节,包括IP头部、TCP头部、MSS长度;MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度;
如果在 TCP 的整个报文(头部 + 数据)交给 IP 层进行分片,会有什么异常呢?
当 IP 层有一个超过 MTU 大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,把数据分片成若干片,保证每一个分片都小于 MTU。把一份 IP 数据报进行分片以后,由目标主机的 IP 层来进行重新组装后,再交给上一层 TCP 传输层。
这看起来井然有序,但这存在隐患的,那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传。
因为 IP 层本身没有超时重传机制,它由传输层的 TCP 来负责超时和重传。
当接收方发现 TCP 报文(头部 + 数据)的某一片丢失后,则不会响应 ACK 给对方,那么发送方的 TCP 在超时后,就会重发「整个 TCP 报文(头部 + 数据)」。
因此,可以得知由 IP 层进行分片传输,是非常没有效率的。
所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,当 TCP 层发现数据超过 MSS 时,则就先会进行分片,当然由它形成的 IP 包的长度也就不会大于 MTU ,自然也就不用 IP 分片了。经过 TCP 层分片后,如果一个 TCP 分片丢失后,进行重发时也是以 MSS 为单位,而不用重传所有的分片,大大增加了重传的效率。
15、第一次握手丢失了,会发生什么?
当客户端想和服务端建立 TCP 连接的时候,首先第一个发的就是 SYN 报文,然后进入到 SYN_SENT
状态。
在这之后,如果客户端迟迟收不到服务端的 SYN-ACK 报文(第二次握手),就会触发「超时重传」机制,重传 SYN 报文。
当客户端在 1 秒后没收到服务端的 SYN-ACK 报文后,客户端就会重发 SYN 报文,那到底重发几次呢?
在 Linux 里,客户端的 SYN 报文最大重传次数由 tcp_syn_retries内核参数控制,这个参数是可以自定义的,默认值一般是 5。
通常,第一次超时重传是在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2 倍。
当第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应 ACK,客户端就不再发送 SYN 包,然后断开 TCP 连接。
所以,总耗时是 1+2+4+8+16+32=63 秒,大约 1 分钟左右。
16、第二次握手丢失了,会发生什么?
当服务端收到客户端的第一次握手后,就会回 SYN-ACK 报文给客户端,这个就是第二次握手,此时服务端会进入 SYN_RCVD 状态。
第二次握手的 SYN-ACK 报文其实有两个目的 :
第二次握手里的 ACK, 是对第一次握手的确认报文;第二次握手里的 SYN,是服务端发起建立 TCP 连接的报文;所以,如果第二次握手丢了,就会发送比较有意思的事情,具体会怎么样呢?
因为第二次握手报文里是包含对客户端的第一次握手的 ACK 确认报文,所以,如果客户端迟迟没有收到第二次握手,那么客户端就觉得可能自己的 SYN 报文(第一次握手)丢失了,于是客户端就会触发超时重传机制,重传 SYN 报文。
然后,因为第二次握手中包含服务端的 SYN 报文,所以当客户端收到后,需要给服务端发送 ACK 确认报文(第三次握手),服务端才会认为该 SYN 报文被客户端收到了。
那么,如果第二次握手丢失了,服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传 SYN-ACK 报文。
在 Linux 下,SYN-ACK 报文的最大重传次数由 tcp_synack_retries内核参数决定,默认值是 5。
因此,当第二次握手丢失了,客户端和服务端都会重传:
客户端会重传 SYN 报文,也就是第一次握手,最大重传次数由 tcp_syn_retries内核参数决定;服务端会重传 SYN-AKC 报文,也就是第二次握手,最大重传次数由 tcp_synack_retries 内核参数决定。
17、第三次握手丢失了,会发生什么?
客户端收到服务端的 SYN-ACK 报文后,就会给服务端回一个 ACK 报文,也就是第三次握手,此时客户端状态进入到 ESTABLISH 状态。
因为这个第三次握手的 ACK 是对第二次握手的 SYN 的确认报文,所以当第三次握手丢失了,如果服务端那一方迟迟收不到这个确认报文,就会触发超时重传机制,重传 SYN-ACK 报文,直到收到第三次握手,或者达到最大重传次数。
注意,ACK 报文是不会有重传的,当 ACK 丢失了,就由对方重传对应的报文。
18、Linux 内核的 SYN
队列(半连接队列)与 Accpet
队列(全连接队列)是如何工作的?
正常流程:
1、当服务端接收到客户端的 SYN 报文时,会将其加入到内核的「 SYN 队列」;2、接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;3、服务端接收到 ACK 报文后,从「 SYN 队列」移除放入到「 Accept 队列」;4、应用通过调用 accpet() socket 接口,从「 Accept 队列」取出连接。
19、什么是 SYN 攻击?如何避免 SYN 攻击?
SYN 攻击
我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的半连接队列,使得服务器不能为正常用户服务。
避免 SYN 攻击方式一
其中一种解决方式是通过修改 Linux 内核参数,控制队列大小和当队列满时应做什么处理。超出处理能力时,对新的 SYN 直接回复RST报文,丢弃连接。
避免 SYN 攻击方式二
当 「 SYN 队列」满之后,后续服务器收到 SYN 包,不进入「 SYN 队列」,启动cookie1、计算出一个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端,2、服务端接收到客户端的应答报文时,服务器会检查这个 ACK 包的合法性。如果合法,直接放入到「 Accept 队列」。3、最后应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接。
20、TCP 四次挥手过程和状态变迁
1、客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。2、服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。3、客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。4、等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。5、客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态6、服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。7、客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。
这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态,需要等待2MSL。
21、为什么挥手需要四次?
-
关闭连接时,客户端向服务端发送
FIN
时,仅仅表示客户端不再发送数据了但是还能接收数据。 -
服务器收到客户端的
FIN
报文时,先回一个ACK
应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送FIN
报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK
和 FIN
一般都会分开发送,从而比三次握手导致多了一次。
22、第一次挥手丢失了,会发生什么?
如果第一次挥手丢失了,那么客户端迟迟收不到被动方的 ACK 的话,也就会触发超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数控制。
当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 设置的次数后,就不再发送 FIN 报文,直接进入到 close 状态。
23、第二次挥手丢失了,会发生什么?
ACK 报文是不会重传的,所以如果服务端的第二次挥手丢失了,客户端就会触发超时重传机制,重传 FIN 报文,直到收到服务端的第二次挥手,或者达到最大的重传次数。
对于 close 函数关闭的连接,由于无法再发送和接收数据,所以FIN_WAIT2 状态不可以持续太久,而 tcp_fin_timeout 控制了这个状态下连接的持续时长,默认值是 60 秒。
这意味着对于调用 close 关闭的连接,如果在 60 秒后还没有收到 FIN 报文,客户端(主动关闭方)的连接就会直接关闭。
24、第三次挥手丢失了,会发生什么?
服务端处于 CLOSE_WAIT 状态时,调用了 close 函数,内核就会发出 FIN 报文,同时连接进入 LAST_ACK 状态,等待客户端返回 ACK 来确认连接关闭。
如果迟迟收不到这个 ACK,服务端就会重发 FIN 报文,重发次数仍然由 tcp_orphan_retries 参数控制,这与客户端重发 FIN 报文的重传次数控制方式是一样的。
25、第四次挥手丢失了,会发生什么?
当客户端收到服务端的第三次挥手的 FIN 报文后,就会回 ACK 报文,也就是第四次挥手,此时客户端连接进入 TIME_WAIT 状态。
服务端(被动关闭方)没有收到 ACK 报文前,还是处于 LAST_ACK 状态。
如果第四次挥手的 ACK 报文没有到达服务端,服务端就会重发 FIN 报文,重发次数仍然由内核参数控制
26、TIME_WAIT 等待的时间是 2MSL?
MSL
是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃 。
2MSL
的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。
在 Linux 系统里 2MSL
默认是 60
秒,那么一个 MSL
也就是 30
秒
27、为什么要等待2MSL?
有两个理由。
一是保证主动关闭端发送的最后一个ACK报文段能够到达被动关闭端。TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。
如果客户端(主动关闭方)最后一次 ACK 报文(第四次挥手)在网络中丢失了,那么按照 TCP 可靠性原则,服务端(被动关闭方)会重发 FIN 报文。
假设客户端没有 TIME_WAIT 状态,而是在发完最后一次回 ACK 报文就直接进入 CLOSED 状态,如果该 ACK 报文丢失了,服务端则重传的 FIN 报文,而这时客户端已经进入到关闭状态了,在收到服务端重传的 FIN 报文后,就会回 RST 报文。为了防止这种情况出现,客户端必须等待足够长的时间确保对端收到 ACK,如果对端没有收到 ACK,那么就会触发 TCP 重传机制,服务端会重新发送一个 FIN,这样一去一来刚好两个 MSL 的时间。
二是防止历史连接中的数据,被后面相同四元组的连接错误的接收。经过2MSL时间就可以使本连接持续时间内所产生的所有报文段从网络中消失,这样就可以使下一个新的连接中不会出现这种旧的报文段。因为初始序列号当增加到一定的大小之后会回绕,当旧的报文段的序列号恰好与当前接收窗口内时,就会接受这个旧连接中的报文段,造成数据混乱。
28、MSL与TTL的区别?
MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。
MSL 与 TTL 的区别: MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。
TTL 的值一般是 64,Linux 将 MSL 设置为 30 秒,意味着 Linux 认为数据报文经过 64 个路由器的时间不会超过 30秒。
29、TIME_WAIT 过多有什么危害?
过多的 TIME-WAIT 状态主要的危害有两种:
-
第一是系统资源占用;
-
第二是对端口资源的占用,一个 TCP 连接至少消耗「发起连接方」的一个本地端口;
第二个危害是会造成严重的后果的,要知道,端口资源也是有限的,一般可以开启的端口为 32768~61000,如果「发起连接方」的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。
客户端(发起连接方)受端口资源限制:
客户端TIME_WAIT过多,就会导致端口资源被占用,因为端口就 65536 个,被占满就会导致无法创建新的连接。服务端(被动连接方)受系统资源限制:
由于一个四元组表示 TCP 连接,理论上服务端可以建立很多连接,因为服务端只监听一个端口,不会因为 TCP 连接过多而导致端口资源受限。但是 TCP 连接过多,会占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等。
30、如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP 有一个机制是保活机制。这个机制的原理是这样的:
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
默认的保活时间为2小时,超过两小时会每隔75秒发送一个探测报文,如果一连9个探测报文都没有得到响应,则认为对方是不可达的,从而断开该连接。也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接 。
应用程序若想使用 TCP 保活机制需要通过 socket 接口设置 SO_KEEPALIVE
选项才能够生效,如果没有设置,那么就无法使用 TCP 保活机制。
如果开启了 TCP 保活,需要考虑以下几种情况:
第一种,对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
第二种,对端程序崩溃并重启。当 TCP 保活的探测报文发送给对端后,对端是可以响应的,但由于没有该连接的有效信息,会产生一个 RST 报文,这样很快就会发现 TCP 连接已经被重置。
第三种,是对端程序崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。
拓展:TCP 保活的这个机制检测的时间是有点长,我们可以自己在应用层实现一个心跳机制。
比如,web 服务软件一般都会提供 keepalive_timeout 参数,用来指定 HTTP 长连接的超时时间。如果设置了 HTTP 长连接的超时时间是 60 秒,web 服务软件就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。
31、如果已经建立了连接,但是客户端的进程崩溃或者主机崩溃会发生什么?
进程崩溃
我自己做了个实验,使用 kill -9 来模拟进程崩溃的情况,发现在 kill 掉进程后,服务端会发送 FIN 报文,与客户端进行四次挥手。
所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。
主机崩溃
在没有开启 TCP keepalive,且双方一直没有数据交互的情况下,如果客户端的「主机崩溃」了,会发生什么。
客户端主机崩溃了,服务端是无法感知到的,在加上服务端没有开启 TCP keepalive,又没有数据交互的情况下,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。
所以,我们可以得知一个点,在没有使用 TCP 保活机制且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态,并不代表另一方的连接还一定正常。
客户端主机宕机,又迅速重启
在客户端主机宕机后,服务端向客户端发送的报文会得不到任何的响应,在一定时长后,服务端就会触发超时重传机制,重传未得到响应的报文。
服务端重传报文的过程中,客户端主机重启完成后,客户端的内核就会接收重传的报文,然后根据报文的信息传递给对应的进程:
-
如果客户端主机上没有进程监听该 TCP 报文的目标端口号,那么客户端内核就会*回复 RST 报文,重置该 TCP 连接;
-
如果客户端主机上有进程监听该 TCP 报文的目标端口号,由于客户端主机重启后,之前的 TCP 连接的数据结构已经丢失了,客户端内核里协议栈会发现找不到该 TCP 连接的 socket 结构体,于是就会回复 RST 报文,重置该 TCP 连接。
客户端主机宕机,一直没有重启
这种情况,服务端超时重传报文的次数达到一定阈值后,内核就会判定出该 TCP 有问题,然后通过 Socket 接口告诉应用程序该 TCP 连接出问题了,然后就会终止该TCP连接
32、listen 时候参数 backlog 的意义?
Linux内核中会维护两个队列:
-
半连接队列(SYN 队列):接收到一个 SYN 建立连接请求,处于 SYN_RCVD 状态;
-
全连接队列(Accpet 队列):已完成 TCP 三次握手过程,处于 ESTABLISHED 状态;
int listen(int fd,int backlog);
fd为文件描述符,backlog在早期 Linux 内核 是 SYN 队列大小,也就是半连接队列大小。
在 Linux 内核 2.2 之后,backlog 变成 accept 队列,也就是已完成连接建立的队列长度,所以现在通常认为 backlog 是 accept 队列。
但是上限值是内核参数 somaxconn 的大小,也就说 accpet 队列长度 = min(backlog, somaxconn)。
服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。
33、accept 发生在三次握手的哪一步?
首先,客户端调用connect函数发起连接,向服务器端发送SYN报文,客户端进入SYN_SENT状态
其次,服务器端收到客户端发来的SYN报文之后,向客户端发送一个SYN+ACK应答报文,并进入SYN_RCVD状态
然后,客户端收到服务器端发来的SYN+ACK报文,connect函数返回,并向服务器端发送ACK应答报文,客户端进入ESTABLISHED状态,
最后,服务器端收到ACK应答报文,accept函数返回,服务器端进入RSTABLISHED状态。
从上面的描述过程,我们可以得知客户端 connect 成功返回是在第二次握手,服务端 accept 成功返回是在三次握手成功之后。
34、TCP怎样保证可靠传输?
1、重传机制
TCP 实现可靠传输的方式之一,是通过序列号与确认应答。 在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。
常见的重传机制:
-
超时重传
-
快速重传
-
SACK
-
D-SACK
超时重传重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传。
TCP 会在以下两种情况发生超时重传:数据包丢失 与 确认应答丢失
这两种情况发送端都会认为数据包没有到达对端,会重传数据包。
RTT
就是数据从网络一端传送到另一端所需的时间,也就是包的往返时间。
超时重传时间是以 RTO
(Retransmission Timeout 超时重传时间)表示。
假设在重传的情况下,超时时间 RTO
「较长或较短」时,会发生什么事情呢?
(1),当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差;(2),当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
精确的测量超时时间 RTO 的值是非常重要的,这可让我们的重传机制更高效。
根据上述的两种情况,我们可以得知,超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。
实际上「报文往返 RTT 的值」是经常变化的,因为我们的网络也是时常变化的。也就因为「报文往返 RTT 的值」 是经常波动变化的,所以「超时重传时间 RTO 的值」应该是一个动态变化的值。
如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是超时间隔加倍。
也就是每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。
超时触发重传存在的问题是,超时周期可能相对较长。那是不是可以有更快的方式呢?
于是就可以用「快速重传」机制来解决超时重发的时间等待。
2、快速重传
快速重传机制的原理是当发送端发送seq1,seq2报文时,seq2报文丢失,接受端只发送了ACK2响应报文,此时再次发送seq3和seq4和seq5时,接收端依然发送ACK2,快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。
快速重传机制只解决了一个问题,就是超时时间的问题,但是它依然面临着另外一个问题。就是重传的时候,是重传之前的一个,还是重传所有的问题。
比如对于上面的例子,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?因为发送端并不清楚这连续的三个 Ack 2 是谁传回来的。
根据 TCP 不同的实现,以上两种情况都是有可能的。可见,这是一把双刃剑。
为了解决不知道该重传哪些 TCP 报文,于是就有 SACK 方法。
3、SACK 方法还有一种实现重传机制的方式叫:SACK( Selective Acknowledgment 选择性确认)。
这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将收到的不连续的字节块的边界发送给发送端,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。
然而,SACK并没有知名发送方应当怎样响应SACK,因此大多数实现还是重传所有未被确认的数据块。
4、Duplicate SACK
Duplicate SACK 又称 D-SACK
,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
可见,D-SACK
有这么几个好处:
-
可以让「发送方」知道,是发出去的包丢了,还是接收方回应的 ACK 包丢了;
-
可以知道是不是「发送方」的数据包被网络延迟了;
-
可以知道网络中是不是把「发送方」的数据包给复制了;
35、TCP面向字节流,无保护消息边界问题的解决?
针对这个问题,一般有3种解决方案:
(1)发送固定长度的消息
(2)设置消息长度字段,把消息的长度与消息一块发送
(3)使用特殊标记来区分消息间隔
36、TCP三次握手失败可能有哪些原因?
(1)可能是请求连接报文出错,如对端IP地址或者端口号错误
(2)服务器端由于某种原因还不能再建立连接,例如遭到攻击、访问量太大导致半连接队列已满等等
(3)客户端和服务器端路由不通。
37、说一下一次完整的HTTP请求过程包括哪些内容?
1、输入网址并进行DNS解析
2、TCP三次握手建立连接,并发送请求报文给服务器端
3、服务器端根据请求报文,生成响应报文并发送给客户端
4、客户端收到响应报文得到html代码,并请求html代码中的资源
5、浏览器对页面渲染呈现给用户
38、你知道DNS是什么
DNS(domain name system)为域名系统,作为IP地址与域名相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记能够被机器直接读取但是不易记的IP数串。
通过域名,获取该域名对应的IP地址的过程叫做域名解析
将域名转换为ip地址,属于应用层协议,使用UDP传输
39、DNS的工作原理?
1、首先,浏览器会查看自身缓存,若有该域名对应的IP地址,则解析结束
2、若未命中,使用gethostbyname函数在系统缓存(如windows中的hosts文件)中查询,若有则解析结束
3、若未命中,则向本地域名服务器发送DNS请求,本地域名服务器查看自身缓存,若有则解析结束,若没有则以自身为DNS客户向根域名服务器发起DNS请求
4、根域名服务器会返回一个顶级域名服务器的地址给本地域名服务器,本地域名服务器再次向顶级域名服务器发送dns请求
5、顶级域名服务会返回一个权威域名服务器地址给本地域名服务器,本地域名服务器再次向权威域名服务器发送dns请求
6、权威域名服务器根据映射关系查询到该域名对应的IP地址并将其返回给本地域名服务器,本地域名服务器将映射关系加入缓存并将这个地址返回给用户,用户再保存到本地缓存中,解析结束
40、为什么域名解析用UDP协议?
因为UDP协议比较快,使用UDP的DNS协议只需一个请求、一个应答即可,而基于TCP的DNS协议需要三次握手、发送数据以及确认应答、四次挥手等,相对于UDP比较繁琐,虽然UDP协议传输的内容不能超过512字节,但是对于DNS查询而言已经足够了。
41、为什么区域传送用TCP协议?
将一个区域文件复制到多个服务器上的过程叫区域传送 。
首先,因为TCP协议实现可靠传输,从主服务器上复制内容到从服务器上,首先要确保的是文件正确的传送给从服务器,而UDP协议不可靠。
其次,UDP协议数据报长度有限制,不能超过512字节,所以对于大文件而言,使用TCP协议比较合适
42、HTTP长连接和短连接的区别
在HTTP1.0中,默认使用短连接,即客户端没发送一个HTTP请求都要重新建立连接,一次通信完毕就立即断开连接。
从HTTP1.1起,默认使用长连接,客户端可以使用同一个连接发送多次HTTP请求,同时TCP有一个保活机制,可以将长时间无活动的连接断开,避免过多无活动连接占用系统资源。
43、什么是TCP粘包/拆包?发生的原因?
在socket通讯过程中,如果通讯的一端一次性连续发送多条数据包,tcp协议会将多个完整的消息(应用层数据)打包成一个tcp报文发送出去,这就是所谓的粘包。而如果通讯的一端发送完整消息超过一次tcp报文所能传输的最大值时,就会将一个数据包拆成多个最大tcp长度的tcp报文分开传输,这就叫做拆包。
粘包原因
1、发送的数据包小于一次tcp报文所能传输的最大值,由于发送速度过快,此时TCP在封装过程中会将多个完整的消息封装成一个TCP数据包;2、发送方数据发送太快,接收方不及时读取套接字缓冲区数据,这将发生粘包。
主要的原因是数据发送过快,数据堆积导致缓冲区积压多个数据后才一次性打包发送出去 或者是 接收方来不及出路缓冲区的数据,出现粘包会导致接收端没有办法解析粘包,因为在TCP的首部没有表示数据长度的字段。
拆包原因
发送的数据包(消息)超过一次tcp报文所能传输的最大值时,就会将一个数据包拆成多个最大tcp长度的tcp报文分开传输。
解决方案
1、发送端给每个数据包添加TCP首部时,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度(简单理解就是,应用层下来的报文前面加上一个报文长度字段);2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来;3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。
44、访问baidu.com的服务器需要经历的流程有哪些?
先通过DHCP协议获得自己的IP地址,随后通过DNS将目标域名解析为目标IP地址,然后判断目标服务器是否与当前IP在一个子网中。若不在,把IP地址通过ARP协议变为物理地址(MAC),发送给路由器。路由器根据路由表找到目标服务器所在的路由器,然后找到目标服务器,进行连接。
45、为什么服务器会缓存这一项功能?如何实现的?
原因
-
缓解服务器压力;
-
降低客户端获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存服务器在地理位置上也有可能比源服务器来得近,例如浏览器缓存。
实现方法
-
让代理服务器进行缓存;
-
让客户端浏览器进行缓存。
46、GET 和 POST 的区别,你知道哪些?
1、GET主要用来获取数据,POST主要用来提交数据,且GET请求提交的数据最大是2K(URL长度限制),而POST没有限制
2、GET请求通过URL(请求行)提交数据,在URL中可以看到所传参数。POST通过“请求体”传递数据,参数不会在url中显示
3、GET对于参数长度有限制,最长为2048字节,且GET的参数放在URL后面以“?”分割,多个参数之间用“&”相连,POST对于参数长度没有限制,且其参数放在请求体中
4、GET请求会被浏览器自动缓存,而POST请求不会,除非手动设置
5、GET请求只能使用URL编码,而POST支持多种编码格式
6、GET请求的参数数据类型只能为ASCII字符,而POST没有限制
7、在某些情况下,GET产生一个TCP数据包,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
POST产生两个TCP数据包,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
8、GET是幂等的,POST不是
幂等性简单来说是对同一URL的多个请求应该返回同样的结果。
47、一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)
在 HTTP/1.1 存在管线化技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的,管线化技术会有队头阻塞问题。
在 HTTP2 中由于多路传输特性的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行。
在 HTTP/1.1 时代,浏览器提高页面加载效率主要通过下面两点:
-
维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
-
和服务器建立多个 TCP 连接。
48、浏览器对同一 Host 建立 TCP 连接到的数量有没有限制?
有限制,如谷歌浏览器最多允许对同一个Host建立六个TCP连接,不同的浏览器有一些区别,取决于浏览器的设置。
49、DNS负载均衡是什么策略?
当一个网站的用户比较多的时候,假如每次的请求都由同一个服务器来处理,则当用户很多时,服务器随时可能崩溃。处理的方法就是DNS负载均衡技术。
原理就是在DNS服务器中为同一个主机名配置多个IP地址,每个IP地址对应一个服务器,在应答DNS查询时,DNS服务器对每个查询以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的。例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等。
50、HTTP 与 HTTPS 有哪些区别?
(1)、HTTP 是超文本传输协议,信息是明文传输,存在安全问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
(2)、HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进行加密报文传输。
(3)、HTTP 的端口号是 80,HTTPS 的端口号是 443。
(4)、HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
51、HTTPS是如何保证数据传输的安全,整体的流程是什么?
图解 ECDHE 密钥交换算法 - 爱码网 (likecs.com)
第一次握手
客户端首先会发一个「Client Hello」消息发起加密通信请求,消息里面有客户端使用的 SSL/TLS协议版本号、支持的密码套件列表,以及生成的随机数(Client Random)。
第二次握手
服务器收到客户端请求后,会返回SeverHello消息。消息的内容包括:
(1)确认 SSL/ TLS 协议版本
(2)服务器产生的随机数(server random)
(3)确认的密码套件
(4)服务器的数字证书。
第三次握手
客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。客户端验证完证书后,认为可信则继续往下走。接着,客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过「Change Cipher Key Exchange」消息传给服务端。
服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
至此,客户端和服务端双方都共享了三个随机数,分别是 Client Random、Server Random、pre-master。
于是,双方根据已经得到的三个随机数,生成会话密钥(Master Secret),它是对称密钥,用于对后续的 HTTP 请求/响应的数据加解密。
生成完会话密钥后,然后客户端发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息。
然后,客户端再发一个「Encrypted Handshake Message」消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。
可以发现,「Change Cipher Spec」之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文。
第四次握手
服务端也会有一个同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。于是,就可以正常收发加密的 HTTP 请求和响应了。
52、如何保证公钥不被篡改?
将服务器公钥放在CA颁发的数字证书中。客户端使用内置的CA公钥验证证书是否是可信的,只要证书是可信的,公钥就是可信的。
53、公钥加密计算量太大,如何减少耗用的时间?
每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。
54、SSL/TLS的基本流程
(1) 客户端向服务器端索要并验证公钥。
(2) 双方协商生成"对话密钥"。
(3) 双方采用"对话密钥"进行加密通信。上面过程的前两步,又称为"握手阶段"(handshake)。
55、HTTP请求和响应报文有哪些主要字段?
1、Host 字段
客户端发送请求时,用来指定服务器的域名。Host:www.baidu.com
2、Connection 字段
Connection 字段最常用于客户端要求服务器使用 TCP 持久连接,以便其他请求复用。
Connection :Keep-AliveHTTP/1.1 版本的默认连接都是持久连接,但为了兼容老版本的 HTTP,需要指定 Connection 首部字段的值为 Keep-Alive
3、Content-Length 字段
服务器在返回数据时,会有 Content-Length 字段,表明本次回应实体主体的数据长度。Content-Length: 1000
同时POST请求传送实体主体时,也需要使用Content-Length字段指定实体主体的长度。
4、Content-Type 字段
Content-Type 字段用于服务器回应时,告诉客户端,本次实体主体数据是什么格式。
Content-Type: text/html; charset=utf-8数据格式为HTML,编码格式为utf-8,类型表明,发送的是网页,而且编码是UTF-8。也可用于浏览器向服务器端传输文件时使用,例如POST、PUT方法
5、Accept 字段
客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式 Accept: / #表示可以接受任何数据
6、Content-Encoding 字段
Content-Encoding 字段说明实体主体的数据的压缩方法。
在客户端请求使用表示客户端可以接受的数据压缩方法,服务器端响应报文中表示此次发送的响应报文所使用的压缩方法。
服务器端Content-Encoding: gzip
客户端Accept-Encoding: gzip, deflate
56、Cookie是什么?用途?
cookie其实就是一些状态信息,类型为“小型文本文件”,存储于电脑上的文本文件中。 一些网站可以使用cookie来跟踪用户。
cookie的是这样工作的。
当客户端访问某个网站时,该网站的服务器就会生成一个唯一的识别码用来标识该客户端,并以此作为索引在服务器的后端数据库中产生一个项目,接着在返回给客户端的响应报文中会添加set-cookie字段,字段值为生成的识别码。
当客户端收到响应之后,就会在它管理的特定cookie文件中添加一行,其中包括服务器的主机名和set-cookie后给出的识别码。以后当客户端再次发送请求报文时,客户端就会从其cookie文件中取出识别码并放到HTTP请求报文中的cookie首部行中,于始网站就能跟踪该客户端的活动。
cookie 的出现是因为 HTTP 是无状态的一种协议,换句话说,服务器记不住你,可能你每刷新一次网页,就要重新输入一次账号密码进行登录。这显然是让人无法接受的,cookie 的作用就好比服务器给你贴个标签,然后你每次向服务器再发请求时,服务器通过HTTP请求报文中的cookie与后端数据库进行对比,就能够 cookie 认出你。
每一个cookie都有一个name和一个value,且name是唯一的。相同名字时,后者会覆盖掉前者(类似哈希表的key的效果)。
一个WEB浏览器也可以存储多个WEB站点提供的Cookie。浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
分类:
1、会话级别的cookie默认情况下它是一个会话级别的cookie,存储在浏览器的内存中,用户退出浏览器之后被删除。
2、持久化的cookie若希望浏览器将该cookie存储在磁盘上,则需要设置该cookie的生命周期setMaxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
用途:
自动登录、跟踪用户上次访问站点的时间、显示最近浏览信息等。
应用场景:
对安全性要求不高,不需要存储大量数据,主要应用场景是用来做客户端与服务器端的状态保持技术。
57、session机制
1、基本介绍session机制采用的是在服务器端保持 HTTP 状态信息的方案。为了加速session的读取和存储,web服务器中会开辟一块内存用来保存服务器端所有的session,每个session都会有一个唯一标识sessionid,并将其写入cookie中,根据客户端传过来的sessionid(cookie中),找到对应的服务器端的session。为了防止服务器端的session过多导致内存溢出,web服务器默认会给每个session设置一个有效期, (30分钟)若有效期内客户端没有访问过该session,服务器就认为该客户端已离线并删除该session。
58、使用 Session 的过程是怎样的?
过程如下:
-
用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
-
服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
-
服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
-
客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。
59、session和cookie的使用
cookie和session的使用已经出现了一些非常成熟的方案。在如今的市场或者企业里,一般有两种存储方式 :
1、存储在服务端:通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session。2、将session数据加密,然后存储在cookie中。这种专业术语叫做client side session。flask采用的就是这种方式,但是也可以替换成其他形式。
60、Cookies和Session区别是什么?
Cookie和Session都是客户端与服务器之间保持状态的解决方案
1,存储的位置不同
-
cookie:存放在客户端
-
session:存放在服务端。Session存储的数据比较安全
2,存储的数据类型不同
两者都是key-value的结构,但针对value的类型是有差异的
-
cookie:value只能是字符串类型
-
session:value是Object类型
3,存储的数据大小限制不同
-
cookie:大小受浏览器的限制,很多是4K的大小
-
session:理论上受当前内存的限制
4,生命周期的控制
-
cookie的生命周期当浏览器关闭的时候,就消亡了,
-
session的生命周期是有时间限制的,一般为30分钟。
61、什么是RARP?工作原理
概括: 反向地址转换协议,网络层协议,RARP与ARP工作方式相反。 RARP使只知道自己硬件地址的主机能够知道其IP地址。
原理:
(1)、主机从网卡上读取MAC地址,然后在网络上发送一个RARP请求的广播数据包,请求RARP服务器回复该主机的IP地址。
(2)、RARP服务器收到了RARP请求数据包,为其分配IP地址,并将RARP回应发送给主机。
(3)、主机收到RARP回应后,就使用得到的IP地址进行通讯。
62、端口有效范围是多少到多少?
0-1023为知名端口号,比如其中HTTP是80,HTTPS是443,FTP是20(数据端口)、21(控制端口)
UDP和TCP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。动态端口的范围是从1024到65535
63、DNS查询方式有哪些?
递归查询、迭代查询
在DNS解析过程中一般是本地域名服务器向上层服务器查询时采用迭代查询,主机向本地域名服务器查询时采用递归查询。
64、HTTP中缓存的私有和公有字段?知道吗?
Cache-control字段指定缓存是私有的或者公有的
Cache-control:private 规定了将资源作为私有缓存,只能被单独用户使用,一般存储在用户浏览器中。
Cache-control:public 规定了将资源作为公共缓存,可以被多个用户使用,一般存储在代理服务器中。
65、GET方法的参数写法是固定的吗?
不是固定的,客户端可以和服务器进行协商参数的写法,只要服务器能够解析出来就行
一般参数都是放在URL后面,用“?”分割,且不同参数之间用‘&’连接
66、GET 方法的URL长度限制是怎么回事?
虽然HTTP 协议没有限制URL,但允许服务器对其进行限制,而且客户端(浏览器)一般也有自己的 URL 长度限制。
服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。
每个浏览器对 URL 长度的最大限制不同,当超过最大限制后页面不会正常打开。
67、GET方法比POST方法安全吗
从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。
要想安全传输,就只有加密,也就是 HTTPS。
对于服务器端而言,get又比post安全,因为get方法不会改变服务器端的数据。对于数据而言是安全的。
68、POST 方法会产生两个 TCP 数据包?你了解吗?
有些文章中提到,POST 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。
HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。
所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。
69、DDos攻击
DDoS 攻击是通过连接互联网的计算机网络进行的。
这些网络由计算机和其他设备(例如 IoT 设备)组成,它们感染了恶意软件,从而被攻击者远程控制。这些个体设备称为机器人(或僵尸),一组机器人则称为僵尸网络。
一旦建立了僵尸网络,攻击者就可通过向每个机器人发送远程指令来发动攻击。
当僵尸网络将受害者的服务器或网络作为目标时,每个机器人会将请求发送到目标的 IP 地址,这可能导致服务器或网络不堪重负,从而造成对正常流量的拒绝服务。
常见的DDos攻击有:HTTP洪水、SYN洪水、DNS放大等
HTTP洪水:HTTP 洪水攻击类似于同时在大量不同计算机的 Web 浏览器中一次又一次地按下刷新——大量 HTTP 请求涌向服务器,导致拒绝服务。
SYN洪水:此类攻击利用 TCP 握手,通过向目标发送大量带有伪造源 IP 地址的 TCP“初始连接请求”SYN 数据包来实现。目标计算机响应每个连接请求,然后等待握手中的最后一步,但这一步确永远不会发生,因此在此过程中耗尽目标的资源。
DNS放大:伪造的服务器的 IP 地址(受害者的 IP 地址)向开放式 DNS 服务器发出请求后,目标 IP 地址将收到服务器发回的响应。 此类攻击试图通过消耗目标与较大的互联网之间的所有可用带宽来造成拥塞。
如何防护 DDoS 攻击?
1、Web 应用程序防火墙
Web 应用程序防火墙(WAF)是一种有效工具,有助于缓解第 7 层 DDoS 攻击。在互联网和源站之间部署 WAF 后,WAF 可以充当反向代理,保护目标服务器,防止其遭受特定类型的恶意流量入侵。
通过基于一系列用于识别 DDoS 工具的规则过滤请求,可以阻止第 7 层攻击。
2、Anycast 网络扩散
此类缓解方法使用 Anycast 网络,将攻击流量分散至分布式服务器网络,直到网络吸收流量为止。
70、MTU和MSS分别是什么?
MTU:maximum transmission unit,最大传输单元,由硬件规定,如以太网的MTU为1500字节。
MSS:maximum segment size,最大报文段长度,是每一个TCP报文段中的数据字段的最大长度。
数据字段加上TCP首部才等于整个TCP报文段。为TCP数据包每次传输的最大数据分段大小,一般由发送端向对端TCP通知对端在每个分节中能发送的最大TCP数据。
71、TCP头部中有哪些信息?
-
源端口:占两字节
-
目的端口:占两字节
-
序号(32bit):传输方向上字节流的字节编号。初始时序号会被设置一个随机的初始值(ISN),之后每次发送数据时,序号值 = ISN + 数据在整个字节流中的偏移。假设A -> B且ISN = 1024,第一段数据512字节已经到B,则第二段数据发送时序号为1024 + 512。用于解决网络包乱序问题。
-
确认号(32bit):接收方对发送方TCP报文段的响应,其值是收到的序号值 + 1。用来解决丢包问题。
-
首部长(偏移量)(4bit):标识首部有多少个4字节 * 首部长,最大为15,即60字节。
-
标志位(6bit):
-
URG:标志紧急指针是否有效。
-
ACK:标志确认号是否有效(确认报文段)。用于解决丢包问题。
-
PSH:提示接收端立即从缓冲读走数据。
-
RST:表示要求对方重新建立连接(复位报文段)。
-
SYN:表示请求建立一个连接(连接报文段),SYN置1,ACK置0,表示连接请求报文。
-
FIN:表示关闭连接(断开报文段)。
-
-
窗口(16bit):接收窗口。用于告知对方(发送方)本方的缓冲还能接收多少字节数据。用于解决流控。
-
校验和(16bit):接收端用CRC检验整个报文段有无损坏。
-
紧急指针(16bit)
72、常见TCP的连接状态有哪些?
-
CLOSED:初始状态。
-
LISTEN:服务器处于监听状态。
-
SYN_SEND:客户端socket执行CONNECT连接,发送SYN包,进入此状态。
-
SYN_RECV:服务端收到SYN包并发送服务端SYN包,进入此状态。
-
ESTABLISH:表示连接建立。客户端发送了最后一个ACK包后进入此状态,服务端接收到ACK包后进入此状态。
-
FIN_WAIT_1:终止连接的一方(通常是客户机)发送了FIN报文后进入。等待对方FIN。
-
CLOSE_WAIT:(假设服务器)接收到客户机FIN包之后等待关闭的阶段。在接收到对方的FIN包之后,自然是需要立即回复ACK包的,表示已经知道断开请求。但是本方是否立即断开连接(发送FIN包)取决于是否还有数据需要发送给客户端,若有,则在发送FIN包之前均为此状态。
-
FIN_WAIT_2:此时是半连接状态,即有一方要求关闭连接,等待另一方关闭。客户端接收到服务器的ACK包,但并没有立即接收到服务端的FIN包,进入FIN_WAIT_2状态。
-
LAST_ACK:服务端发动最后的FIN包,等待最后的客户端ACK响应,进入此状态。
-
TIME_WAIT:客户端收到服务端的FIN包,并立即发出ACK包做最后的确认,在此之后的2MSL时间称为TIME_WAIT状态
73、TCP的流量控制
1、当接收方的发送给发送方的报文段设置窗口为0,表示发送方不能再发送数据了,之后如果接收方的接收缓存又有了一些存储空间,会发送一个rwnd=XXX的报文段,如果这个报文段丢失,会造成发送方和接收方均一直等待的情况,为了解决这种问题,TCP为每一个连接都设置一个持续计时器,只要TCP连接的一方收到对方的零窗口通知就启动持续计时器,若持续计时器设置的时间到了,就发送一个零窗口探测报文段,而对方在收到这个报文段时就将现在的窗口值给出。如果还是0,则重置持续计时器。
TCP的传输效率
1、Nagle算法
纳格尔算法为防止数据包过多而发生网络过载,应用于TCP层。在网络负载比较大时,主要防止极其短小的报文段的发送,尽可能的缓存,使得报文段尽可能的长(不超过MSS)
使用纳格尔算法时,只有收到前一数据的ACK消息时才会发送下一数据。
TCP套接字默认使用Nagle算法交换数据,因此最大限度的进行缓冲,直到收到ACK。不使用纳格尔算法时,将对网络流量产生负面影响,有时即使只传输一个数据,其头部信息都有可能是几十字节,因此,若是为了提高网络效率必须使用纳格尔算法。
根据传输数据的特性,网络流量未受太大影响时,不使用Nagle算法要比使用它时传输速度快。例如“传输大文件数据”。将文件数据传入输出缓冲不会花太多时间,因此,即便不使用Nagle算法,也会在装满输出缓冲时传输数据包。这不仅不会增加数据包的数量,反而会在无需等待ACK的前提下连续传输,因此可以大大提高传输速度。 一般情况下,不使用纳格尔算法会提高传输速度。禁用纳格尔算法方式:setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(void*)&opt_val,sizeof(opt_val));
2、糊涂窗口综合征
假设TCP缓存已满,则应用程序每次从缓存中提取1字节数据,然后就向发送方发送确认报文并设置串口为1字节,接着发送方发送1字节数据,接收方确认,仍然将窗口设置为1,这样下去,网络效率很低,即为”糊涂窗口综合征“
解决办法:可以让接收方等待一段时间,等到接收缓存可以容纳一个最长的报文段或者接受缓存已有一半的空闲空间,再向发送发送确认报文,并通知当前窗口大小。
74、TCP的拥塞控制
1、拥塞控制:所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或者链路不致过载。
网络拥塞往往是很多因素引起的,例如,节点(路由器)缓存太小,导致很多分组因为无存储空间暂存而丢弃,就算扩大缓存,则分组在缓存中等待的时间过程,发送分组的源点也早就开始超时重传了,造成网络资源的浪费。
现在通信线路的传输质量一般都很好,因为传输出差错而丢失分组的概率是很小的,因此判断网络拥塞的依据就是出现了超时。
2、TCP的拥塞控制
TCP的拥塞控制涉及四种算法:慢开始、拥塞避免、快重传、快恢复算法。
发送方维护一个拥塞窗口的状态变量,拥塞窗口的大小取决于网络的拥塞程度,并且动态的变化,发送方让自己的发送窗口等于拥塞窗口。
控制流程如下:
1、慢开始
当主机开始发送数据时,由于不知道网络的负荷情况,所以较好的方法就是先探测一下,即由小到大增大发送窗口(拥塞窗口),具体规定如下:smss为发送方的最大报文段长度
(1)smss>2190:初始拥塞窗口设为cwnd=2*smss;
(2)2190>=smss>1095:cwnd=3*smss;
(3)smss<=1095:cwnd=4*smss;
慢开始规定,在收到一个报文段确认之后,就增加一个smss的长度,所以使用慢开始算法,没经过一个传输轮次,拥塞窗口就加倍。在TCP的实际行动中,每收到一个对新报文段的确认,拥塞窗口就加一,并立即传输新的报文段。
为防止拥塞窗口过大,引起网络拥塞,所以还需要设置一个慢开始门限ssthresh,当超过这个门限时就采用拥塞避免算法,否则就使用慢开始算法。
2、拥塞避免算法
当拥塞窗口大于ssthresh时,采用拥塞避免算法,具体思路就是每经过一个往返时间cwnd就加1,即”加法增大“,此时拥塞窗口按线性规律缓慢增长,比慢开始算法的增长速率缓慢的多。
当出现超时的情况时,发送方就判断发生了网络拥塞,此时将慢开始门限设为当前cwnd的一半,即ssthresh=cwnd/2,而cwnd设为1,重新启动慢开始算法。
3、快重传算法
快重传算法作用在接收方和发送方,可以让发送方尽早的知道个别报文段的丢失,其首先要求接收方不要进行捎带确认,而是立即发送确认,即使收到收到了失序的报文段也要立即发送自己目前接收到的有序报文段的重复确认。发送方只要一连收到三个重复确认,就会立即进行重传,这样就不会出现超时,发送方也不会认为出现网络拥塞。
4、快恢复算法
当发送方一连收到三个重复确认,就知道只是丢失了个别报文段,就不启动慢开始,而是执行快恢复算法,将ssthresh设为当前拥塞窗口的一半,即ssthresh=cwnd/2,然后再将cwnd=ssthresh,并开始执行拥塞避免算法。快恢复算法又称为乘法减小,与拥塞避免合称”AIMD算法“
TCP复用
TCP连接复用是将多个客户端的HTTP请求复用到一个服务器端TCP连接上,而HTTP复用则是一个客户端的多个HTTP请求通过一个TCP连接进行处理。前者是负载均衡设备的独特功能;而后者是HTTP 1.1协议所支持的新功能,目前被大多数浏览器所支持。
TCP缓冲
通过采用TCP缓冲技术,可以提高服务器端响应时间和处理效率,减少由于通信链路问题给服务器造成的连接负担。
tcp/udp可以绑定同一个端口吗(镜像问题)
tcp/udp均不可以两个同类的监听socket绑定在同一个端口上。
但是可以一个tcp一个udp同时绑定一个端口。
由上述结果可知:TCP、UDP可以同时绑定一个端口8888,但是一个端口在同一时刻不可以被TCP或者UDP绑定2次。原因如下:
-
tcp的端口不是物理概念,仅仅是协议栈中的两个字节;
-
TCP和UDP的端口完全没有任何关系,完全有可能又有一种XXP基于IP,也有端口的概念,这是完全可能的;
-
TCP和UDP传输协议监听同一个端口后,接收数据互不影响,不冲突。因为数据接收时时根据五元组{传输协议,源IP,目的IP,源端口,目的端口}判断接受者的。
详细解释下什么是HTTP?
简单来说,HTTP即为超文本传输协议,是一个在计算机世界里专门在两点之间传递文字、图片、视频、音频等超文本数据的约定和规范。可以在浏览器和服务器之间传输数据,也可以在服务器与服务器之间传输数据。
拓展:「文本」,在互联网早期的时候只是简单的字符文字,但现在「文本」的涵义已经可以扩展为图片、视频、压缩包等,在 HTTP 眼里这些都算作「文本」。
再来理解「超文本」,它就是超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。HTML 就是最常见的超文本了,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,再经过浏览器的解释,呈现给我们的就是一个文字、有画面的网页了。
UDP如何实现可靠性传输?
UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。实现确认机制、重传机制、窗口确认机制。如果你不利用linux协议栈以及上层socket机制,自己通过抓包和发包的方式去实现可靠性传输,那么必须实现如下功能:发送:包的分片、包确认、包的重发接收:包的调序、包的序号确认
目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。
RSA算法?
RSA算法是一种非对称公钥加密算法。
音视频协议总结
RTSP简介
RTSP(Real Time Streaming Protocol 实时流协议)建立并控制一个或几个时间同步的连续流媒体,对媒体流提供了诸如开始、暂停、快进、停止等控制,RTSP的作用相当于流媒体服务器的远程控制,而它本身并不传输数据。
RTSP具有重新导向功能,可视实际负载情况来转换提供服务的服务器,以避免过大的负载集中于同一服务器而造成延迟。
RTSP协议与HTTP协议的语法非常类似,且都是纯文本协议,但它们也有区别:
-
RTSP是有状态的,它命令总是按照顺序来发送,其中某个命令可能需要总在另外一个命令之前要发送。而HTTP则是无状态,协议在发送一个命令以后,连接就会断开,且命令之间是没有依赖性的。
-
RTSP协议使用554端口,HTTP使用80端口。
-
RTSP请求,服务器和客户端都可以发送,而HTTP请求则只能由客户端发送
RTSP的有很多优点:
-
易扩展:RTSP中很容易加入新的方法及参数,只需要服务器和客户端共同协商即可
-
易解析:RTSP可以由标准HTTP或MIME解析器进行解析
-
安全:RTSP使用网页安全机制,所有HTTP授权机制如basic、digest都可以直接使用
-
传输协议多选:RTSP可以使用TCP()或UDP作为其底层传输协议支持
-
多服务器支持:请求的多股流可以放在不同的服务器上,客户端自动与这几个服务器建立连接,在传输时完成媒体流同步
RTSP常用的方法包括:
OPTIONS:C->S 获在任意时刻由客户端主动发出,取服务器支持的方法。它不影响服务器的状态
DESCRIBE:C->S 向服务器获取URL指定的媒体对象的描述,其中Accept字段指定了描述格式
ANNOUNCE:C->S / S->C 当客户端向服务器发送时,表示的是将通过请求 URL 识别的表示描述或者媒体对象提交给服务器,当服务器向客户端发送时,表示的是通知客户端更新会话信息
SETUP
TEARDOWN
PLAY
PAUSE
GET_PARAMETERSE
T_PARAMETER
RTP协议详解
RTP全名是Real-time Transport Protocol(实时传输协议)。RTP是一种运行在传输层的协议,通常基于UDP协议,但也支持 TCP 协议 。
-
RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。
-
RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。
RTP数据包由两部分组成
-
一部分是RTP Header,RTP Header占用最少12个字节,最多72个字节;
-
另一部分是RTP Payload,用来封装实际的数据负载,例如h264的裸码流数据。
RTP的工作机制
当应用程序提供RTSP协议建立一个RTP会话时,应用程序将确定一对目的传输地址(一个网络地址和两个端口号),其中两个端口号中的偶数端口是分配给RTP进行裸码流数据传输的,奇数端口则是分配给RTCP进行传输控制的。
RTP的发送过程如下:
-
从上层接收流媒体信息码流(如H.264),封装成RTP数据包;RTCP从上层接收控制信息,封装成RTCP控制包。
-
将RTP 数据包发往UDP端口对中偶数端口;将RTCP控制包发往UDP端口对中的接收端口。
RTP Header解析
前12字节是固定的,CSRC可以有多个或者0个。
1)V:RTP协议的版本号,占2位,当前协议版本号为2
2)P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分
3)X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头
4)CC:CSRC计数器,占4位,指示CSRC标识符个数
5)M:标志,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
6)PT(payload type):有效荷载类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是用来区分音频流和视频流,这样便于客户端进行解析。
7)序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。这个字段当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包。当出现网络抖动的情况可以用来对数据进行重新排序。序列号的初始值是随机的,同时音频包和视频包的sequence是分别计数的。
8)时间戳(Timestamp):占32位,必须使用90kHZ时钟频率(程序中的90000)。时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。可以根据RTP包的时间戳来获得数据包的时序。
9)同步信源(SSRC)标识符:占32位,用于标识同步信源。同步信源是指产生媒体流的信源,他通过RTP报头中的一个32位数字SSRC标识符来标识,而不依赖网络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报文的分组。
10)提供信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个CSRC。每个CSRC标识了包含在RTP报文有效载荷中的所有提供信源。
提供信源用来标识对一个RTP混合器产生的新包有贡献的所有RTP包的源。是指当混合器接收到一个或多个同步信源的RTP报文后,经过混合处理产生一个新的组合RTP报文,并把混合器作为组合RTP报文的SSRC,将原来所有的SSRC都作为CSRC传送给接收者,是接受者知道组成组合报文的各个SSRC。
RTCP协议与RTP协议的关系
源端利用RTCP报文同步一次会话中的不同媒体流。例如,在一次视频会议应用中,每一个源端都产生两个独立的媒体流,一个用于传输视频,一个用于传输音频。这时,需要将这些RTP报文头中的时间戳与视频、音频采样时钟建立关联。由于源端发出的RTCP报文包含与它关联的RTP报文流的时间戳与真实时间,因此接收端可以通过RTCP报文提供的关联来同步视频与音频的播放。
实际上,RFC 3550文档定义了两部分的内容。一部分是用于传输多媒体数据流的协议(RTP),另一部分是实时传输控制协议(RTCP)。
RTCP与RTP协议是相互配合的关系。RTP与RTCP可以同时在一个多媒体应用中使用,都封装在UDP报文中传输。
RTP报文的有效载荷中封装音频、视频数据流,而RTCP报文不封装任何音频、视频数据流。
RTCP报文类型
RTCP报头中有一个长度为8比特的报文类型字段,不同报文类型字段值表示不同类型的RTCP报文。例如,报文类型字段值为200,表示发送端报告的RTCP报文。
发送端报告(SR)发送端与接收端的一次会话包含很多RTP流。发送端每次发送一个RTP流时,就会发送一个SR报文。
绝对时间对于多媒体传输是非常重要的。在传输一个视频信号时,实际上需要同时传输音频流与图像流。这样,在播放一个视频节目时,通过RTP报文的时间戳与绝对时间可实现音频流与图像流的同步。
接收端报告(RR)接收端每次接收一个RTP流时,就会发送一个RR报文。接收端可以使用RTCP报文,周期性地向发送端反馈与QoS相关数据。发送端可以根据RTCP报文反馈的信息,了解网络当前的延时与延时抖动、丢包率,以便决定数据传输速率。如果网络通信状态良好,发送端可以动态改变编码算法,以提高多媒体信息的播放质量。
发送端描述报告(SDES)发送端周期性地通过多播方式发送SDES报文,给出了会话参与者的规范名(Canonical Name)。规范名是会话参与者电子邮件地址的字符串。
结束(BYE)结束(BYE)报文用来关闭一个数据流。在视频会议应用中,一个发送端通过结束报文宣布退出这次会议。
特定应用(APP)特定应用(APP)报文用于应用程序定义一种新的RTP报文类型。
在通常情况下,RTCP报文占用的网络带宽不应超过5%。如果一个发送端正在以2Mbps速率发送视频流,那么该节点的RTCP报文占用带宽必须低于100kbps。在具体的实现中,通常将这个带宽的75%(75kbps)分配给接收端,剩余25%(25kbps)留给接收端。如果在多播情况下有n个接收端,那么每个接收端用于发送RTCP报文的带宽应控制在75/n(kbps)之内。