1.TCP头部3字段有哪些,有什么作用?
源端口号 目的端口号:
作用是标识唯一标识一个连接(源IP和目标IP在IP层已处理过)
序列号字段:
即Sequence Number,指的是报文段的第一个字节的序列号
作用是在SYN报文中交换彼此的初始序列号,保证数据包按照正确的顺序组装
确认号字段:
即ACK,用来告知对方下一个期望接受到的序列号,小于ACK的所有字节已经全部收到
----------------------------------------------------1.拓展内容--------------------------------------------------------------
标记位字段:
头部长度
常见的标志位有SYN,ACK,FIN,RST,PSH(SYN和ACK上文已说过)
FIN:即Finish,表示发送方准备断开连接
RST:即Reset,用来强制断开连接
PSH:即Push,告知对方这些数据包收到后应该马上交给上层应用,不能缓存
窗口大小
占两个字节,可以扩容,可以将窗口扩大为原来的2^n
校验位:
占用两个字节,防止运输过程中数据包有损坏,如果遇到校验有差错的报文,TCP直接丢弃等待重传
可选项:
---------------------------------------------------------------------------------------------------------------------------------
2.TCP协议工作在哪一层,为什么需要TCP协议?
TCP工作在传输层,TCP由于其传输可靠性可以极大程度上减少数据丢失的情况,保证数据包可靠性
3.什么是TCP连接?
在发送数据前,相互通信的双方(即发送方和接收方)需要建立一条连接,在发送数据后通信双方需要断开连接,这就是TCP连接的建立与终止
4.如何唯一确定一个TCP连接呢?
通过源IP目的IP(IP层),源端口号,目的端口号(TCP层)确定一个TCP连接
5.UDP和TCP有什么区别呢?分别应用的场景是?
UDP协议是不可靠传输协议,TCP是可靠的传输协议,在数据传输可靠性方面有区别,UDP会比TCP的数据传输可靠性低,TCP协议在连接性上面向连接,UDP无连接,在报文方面,TCP的报文面向字节流,UDP面向报文,在效率上,TCP的传输效率低,UDP的传输效率高,在流量控制和拥塞控制中,TCP针对流量控制有滑动窗口,对拥塞控制有慢开启,拥塞避免,快重传,快恢复,而UDP对流量控制和拥塞控制无相应对策,在传输速度方面TCP较UDP慢。
TCP的应用场景主要是在对效率要求低,对准确性要求高或者要求有连接的场景
UDP的应用场景主要是在对效率要求高,对准确性要求较低的场景使用
-----------------------------------------------------拓展----------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------
6.为什么是三次握手?不是两次、四次?
为了实现可靠数据传输,TCP协议的通信双方都必须维护一个序列号,以表示发送出去的数据包中,哪些是已经被对方收到的。三次握手的过程是通信双方相互告知序列号起始值,并且确认对方已经收到了序列号初始值的必经步骤。
如果只有两次握手,至少只有连接发起方的初始序列号被确认,但是另一方选择的序列号不能确认
由于三次握手过程已经可以确认TCP连接,再加入一次握手过程则会降低TCP连接的速度与效率
7.为什么每次建立TCP连接时,初始化序列号的要求不一样呢?
ISN报文(Initial Sequence Number 初始序列号):
在三次握手的过程当中,双方会用SYN报文来交换彼此的ISN
这种加密方式作用在于如果ISN被攻击者预测到,要知道源IP和源端口号都是很容易伪造的,当攻击者猜测ISN之后,直接伪造一个RST后,就可以强制连接关闭,而动态增长的难预测的ISN大大提高了猜测ISN的难度
8.初始序列号ISN是如何随机产生的?
ISN的计算值是根据每4ms加1,溢出则回到0的动态增长方式计算值
9.既然IP层会分片,为什么TCP层还需要MSS呢?
根据作用不同,分片会采取不同的大小分片,在IP层分片传输中,一旦某个分片丢失,则会造成整个IP数据包作废,所以TCP也引入了MSS,就是在TCP层进行分配,防止IP分片过大导致出现数据包丢失重传效率和速度降低
10.第一次握手丢失了,会发生什么?
出现第一次握手数据包丢失会发生超时重传现象,客户端没有收到SYN-ACK报文则会重新向另一连接方发送SYN报文,如果继续丢失则还会触发超时重传现象,达到一定循环重传次数后客户端则会停止重传断开连接
11.第二次握手丢失了,会发生什么?
第二次握手会发送第一次握手的ACK确认报文,如果客户端没有收到第二次握手则会触发超时重传机制客户端重新发送第一次握手ACK
12.第三次握手丢失了,会发生什么?
会触发超时重传机制,服务端发送SYN-ACK报文直到第三次握手成功或者达到最大限度为止
13.什么是SYN攻击,如何避免SYN攻击?
SYN攻击是指攻击方使用伪造的IP地址向被攻击方发送请求,而被攻击方发送的确认报文一直发送不到目的地,在其过程中消耗的资源越来越多导致主机资源浪费直到耗尽
避免SYN攻击则需要加强初始序列号的加密
14.TCP四次挥手的过程是怎样的?
首先客户端应用程序发出释放连接的报文段,并且停止发送数据,主动关闭TCP连接,报文中首部FIN位置为1,不包含数据,序列号位seq=u,此时客户端主机进入FIN-WAIT-1(终止等待1)阶段
服务器主机接收到客户端发出的报文段后即发出确认应答报文,确认应答报文中ACK=1,生成自己的序号位seq=v,ack=u+1,然后服务器主机进入CLOSE-WAIT(关闭等待)状态
客户端主机收到服务器主机确认应答后即进入FIN-WAIT-2(终止等待2)状态,等待客户端发出成功连接释放的报文段
这时服务器主机会发出断开连接的报文段,报文段中ACK=1,序列号seq=v,ack=u+1,在发送完断开请求的报文后服务器主机就进入了LAST-ACK(最后确认)的阶段
客户端收到服务端的断开连接请求后,客户端要做出相应,客户端发出断开连接的报文段,在报文段中,ACK=1,序列号seq=u+1,因为客户端从连接开始断开后就没有再发送数据,ack=v+1,然后进入到TIME-WAIT(事件等待)状态,此时这个时候TCP连接还没有被释放,必须经过时间等待设置,也就是2MSL后,客户端才会进入CLOSED状态
(时间MSL叫做最长报文段寿命)
服务端主要收到了客户端的断开连接确认后,就会进入CLOSED状态,因为服务端结束TCP连接时间要比客户端早,而整个断开连接需要发送四个报文段
15.为什么挥手要四次?
在客户端主动关闭的情况下,服务端收到客户端的FIN报文时,只能表示客户端没有数据发送给服务端了,但服务端可能还有数据需要发送给客户端,所以服务端可能并不会立即关闭SOCKET,而是先回复一个ACK报文告诉客户端已经收到FIN了,只有等到服务器所有报文都发送完了才发送FIN报文,也就是说被动关闭方的ACK和FIN报文多数情况下都是分开发送的,所以需要四次交互
16.第一次挥手丢失了,会发生什么?
第一次挥手丢失后,客户端一直没有收到被动方的ACK就会触发超时重传机制,重传FIN报文,如果超过设定重传次数后将不再发送FIN报文,在等待一段时间(时间为上一次超时时间的二倍)后如果还是没有收到二次挥手则直接进入到CLOSE状态
17.第二次挥手丢失了,会发生什么?
由于ACK报文不会重传,如果服务端的第二次挥手丢失了,客户端就会触发超时重传机制,重传FIN报文,直到收到服务端的第二次挥手,或者达到最大重传次数
18.第三次挥手丢失了,会发生什么?
由于ACK报文不会重传,如果第三次挥手丢失了,服务端就会触发超时重传机制,服务端就会重发FIN报文直到超过最大重传次数
19.第四次挥手丢失了,会发生什么?
由于ACK报文没有到达服务端,服务端就会重发FIN报文,重发次数经最大重发次数控制
20.为什么TIME_WAIT等待的时间是2MSL?
TIME_WAIT等待时间设置为2MSL就能够让TCP重新发送最终的ACK以避免出现丢失的情况,重新发送最终的ACK并不不是因为TCP重传了ACK,而是因为通信另一方重传了FIN
21.为什么需要TIME_WAIT状态?
1 保证被动关闭连接的一方能被正确的关闭
TCP 协议在关闭连接的四次挥手中,在主动关闭方发送的最后一个 ACK 报文,有可能丢失,这时被动方会重新发 FIN 报文, 如果这时主动方处于 CLOSE 状态 ,就会响应 RST 报文而不是 ACK 报文。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSE。
2 防止历史连接中的数据被后面相同的四元组的连接错误的接收
TCP 报文可能由于路由器异常而 “迷路”,在迷途期间,TCP 发送端可能因确认超时而重发这个报文,迷途的报文在路由器修复后也会被送到最终目的地,这个原来的迷途报文就称为 lost duplicate。在关闭一个 TCP 连接后,马上又重新建立起一个相同的 IP 地址和端口之间的 TCP 连接,后一个连接被称为前一个连接的化身,那么有可能出现这种情况,前一个连接的迷途重复报文在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情 况, TIME_WAIT 状态需要持续 2MSL,因为这样就可以保证当成功建立一个 TCP 连接的时候,来自连接先前化身的重复报文已经在网络中消逝。
22.TIME_WAIT过多有什么危害?
1 占用端口资源
2 占用系统资源 如文件描述符、内存资源、CPU资源等
23.服务器出现大量TIME_WAIT状态的原因有哪些?
1 HTTP未使用长连接
2 HTTP长连接超时
3 HTTP长连接的请求数量达到上限
24.服务器出现大量CLOSE_WAIT状态的原因有哪些?
1 没有将服务端socket注册到epoll,这样有新的连接到来时,服务端没法感知这个时间就无法获取已连接的socket,那服务端自然就没机会对socket调用close函数了(第二步)
2 有新的连接到来时没有调用accept获取该连接的socket,导致当有大量的客户端主动断开了连接而服务器没机会对这些socket调用close函数,从而导致出现大量CLOSE_WAIT状态的连接
(第三步)
3 通过accept获取已连接的socket后,没有将其注册到epoll,导致后序收到FIN报文的时候,服务端没有办法感知这个事件,那服务器就没办法调用close函数了(第四步)
4 当发现客户端关闭后,服务器没有执行close函数,可能是因为代码漏处理,或者是在执行close函数之前,代码卡在某个逻辑,如死锁(第六步)
--------------------------------------------------拓展:TCP服务端流程-------------------------------------------------
- 创建服务端 socket,bind 绑定端口、listen 监听端口
- 将服务端 socket 注册到 epoll
- epoll_wait 等待连接到来,连接到来时,调用 accpet 获取已连接的 socket
- 将已连接的 socket 注册到 epoll
- epoll_wait 等待事件发生
- 对方连接关闭时,我方调用 close
---------------------------------------------------------------------------------------------------------------------------------
25.如果已经建立了连接,但是服务器出故障了怎么办?
TCP设有一个保活计时器,服务器每收到一次客户端的请求后,都会重新复位这个计时器,时长通常设置为2个小时,如果两个小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后没间隔75秒发送一次,如果一连发了10个探测报文仍然没响应,服务器就认为客户端出了问题,关闭连接。
26.如果已经建立了连接,但是服务器进程崩溃了怎么办?
进程崩溃后服务端会向客户端发送FIN报文,进行四次挥手
27.针对TCP如何socket编程?
- 服务端和客户端初始化
socket
,得到文件描述符; - 服务端调用
bind
,将 socket 绑定在指定的 IP 地址和端口; - 服务端调用
listen
,进行监听; - 服务端调用
accept
,等待客户端连接; - 客户端调用
connect
,向服务端的地址和端口发起连接请求; - 服务端
accept
返回用于传输的socket
的文件描述符; - 客户端调用
write
写入数据;服务端调用read
读取数据; - 客户端断开连接时,会调用
close
,那么服务端read
读取数据的时候,就会读取到了EOF
,待处理完数据后,服务端调用close
,表示连接关闭。
这里需要注意的是,服务端调用 accept
时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。
所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket
一个叫作监听 socket,一个叫作已完成连接 socket。
28.listen时候backlog的意义?
设置请求队列的长度
29.accept发生在三次握手的哪一步?
accept发生在三次握手之后
30.客户端调用close了,连接断开的流程是什么?
客户端调用close()后,向服务端发送FIN,服务端会用FIN-ACK。 服务端进入TIME-WAIT状态,客户端直接进入CLOSE状态,连接结束。
31.没有accept可以建立TCP连接吗?
服务端即使不调用accept,客户端依然可以connect成功。
当客户端调用connect函数时,将引发三次握手过程,客户端首先发送SYN请求分组,此时服务端会将请求放入SYN队列,同时向客户端发送ACK确认报文,然后客户端向服务端再次发送ACK报文。 服务端收到ACK确认报文后,将SYN里的连接请求移入ACCEPT队列。 此时三次握手结束,即TCP连接成功建立。
32.没有listen可以建立TCP连接吗?
可以。
客户端是可以自己连自己的形成连接(TCP自连接),也可以两个客户端同时向对方发出请求建立连接(TCP同时打开),这两个情况都有个共同点,就是没有服务端参与,也就是没有listen,就能建立连接。
33.什么是超时重传?
如果发送方在一定时间内未收到确认,会认为数据可能丢失,触发数据的重传的一种机制
34.什么是快速重传?(需补充)
快速重传机制是基于接收端的反馈信息来触发的,它不受计时器影响,与超时重传相比能有效的修复丢包情况,当TCP连接的过程中接收端出现乱序的报文如2-4-3到达时,TCP需要立刻生成确认消息,这种确认消息也被称为重复ACK
35.什么是SACK方法?
在TCP报文段中,SACK是一个选项字段(Selective Acknowledgement),这种字段是一种选择性确认机制,这个机制能告诉TCP客户端未接收到的数据包范围(SACK选项只出现在SYN段中)
36.操作系统缓冲区与滑动窗口的关系是什么?
TCP的滑动窗口大小实际上就是socket的接收缓冲区大小的字节数
37.什么是窗口关闭?
38.什么是糊涂窗口综合征?
糊涂窗口综合症是指当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢,或二者兼而有之;就会使应用进程间传送的报文段很小,特别是有效载荷很小; 极端情况下,有效载荷可能只有1个字节;传输开销有40字节 (20字节的IP头+20字节的TCP头) 这种现象。
39.什么是慢启动?
慢启动,是TCP使用的一种阻塞控制机制,也叫做指数增长期,是指每次TCP接收窗口收到确认时都会增长,增长的大小就是已确认段的数目,这种情况一直保持到要么没有收到一些段,要么窗口大小到达预先定义的阈值。 如果发生丢失事件,TCP就认为这是网络阻塞,就会采取措施减轻网络拥挤。
当一个新的TCP连接建立或检测到由重传超时(RTO)导致的丢包时,需要执行慢启动,TCP发送端长时间处于空闲状态也可能调用慢启动算法,目的是使TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值以帮助TCP建立ACK时钟,通常TCP在建立新连接时执行慢启动,直至有丢包时执行拥塞避免算法
指数增长cwnd=cwnd^2
40.什么是拥塞避免算法?
一旦慢启动达到阈值时,就会启用拥塞避免算法,TCP就会进入拥塞避免阶段
累加增长cwnd+1
41.拥塞发生是什么?
触发超时重传机制后就进入了拥塞发生算法
阈值设置为cwnd/2
cwnd重置为1
42.什么是快速恢复?
快速恢复和快速重传算法一般同时使用,快速算法认为你还能收到三个重复ACK说明网络也没有那么糟糕,所以没必要像RTO超时那么强烈
拥塞窗口cwnd=阈值+3(3的意思是确认有3个数据包被收到)
重传丢失的数据包
如果再收到重复的ACK,那么cwnd+1
如果收到新数据的ACK后,把cwnd设置为第一步中的阈值,原因是该ACK确认了新的数据说明从最后发的ACK后的数据包都已经收到了,恢复进程结束,可以回到之前的状态,再次进入拥塞避免状态