计算机网络笔记,持续完善中
计算机网络
TCP
-
TCP状态转换图
-
TCP流量控制和拥塞控制的实现?
-
流量控制:TCP采用大小可变的滑动窗口进行流量控制。窗口大小的单位是字节,在TCP报文段首部的窗口字段写入的数值就是当前给对方设置的发送窗口数值的上限,发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方的发送窗口上限值
-
拥塞控制:网络拥塞现象是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象。严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象。拥塞控制是处理网络拥塞现象的一种机制
-
方法:有一个叫慢启动门限
ssthresh
(slow start threshold)状态变量,一般来说ssthresh
的大小是65535
字节- 慢开始( slow-start ):当
cwnd
<ssthresh
时,使用慢启动算法,每当收到一个 ACK 时,指数级增长cwnd
,如1,2,4,8… - 拥塞避免( congestion avoidance ):当
cwnd
>=ssthresh
时,就会使用拥塞避免算法,线性增长cwnd
,每当收到一个 ACK 时,cwnd
增加1/cwnd
。一直增长着,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。当触发了重传机制,也就进入了「拥塞发生算法」 - 超时重传:
ssthresh
设为cwnd/2
,cwnd
重置为 1,重新开始慢开始算法 - 快重传( fast retransmit ):当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则
ssthresh
和cwnd
变化如下:cwnd
=cwnd/2
,也就是设置为原来的一半;ssthresh
=cwnd
;进入快速恢复算法 - 快恢复( fast recovery ):拥塞窗口
cwnd
=ssthresh
+ 3( 3 的意思是确认有 3 个数据包被收到了)- 重传丢失的数据包
- 如果再收到重复的 ACK,那么
cwnd
增加 1 - 如果收到新数据的 ACK 后,把
cwnd
设置为第一步中的ssthresh
的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态
- 慢开始( slow-start ):当
-
-
-
TCP重传机制
- 滑动窗口机制,确立收发的边界,能让发送方知道已经发送了多少、尚未确认的字节数、尚待发送的字节数;让接收方知道已经确认收到的字节数
- 选择性重传,用于对传输出错的序列进行重传
-
三次握手过程
- 主动建立连接方A的TCP向主机B发出连接请求报文段,其首部中的
SYN
(同步)标志位应置为1,表示想与目标主机B进行通信,并发送一个同步序列号x
进行同步,表明在后面传送数据时的第一个数据字节的序号是x + 1
。SYN
同步报文会指明客户端使用的端口以及TCP连接的初始序号,A进入SYN_SENT
状态 - 接收连接方B的TCP收到连接请求报文段后,如同意则发回确认。在确认报中应将
ACK
位和SYN
位置1,表示客户端的请求被接受。确认号应为x + 1
,同时也为自己选择一个序号y
,B进入SYN_RCVD
状态 - 主动方A的TCP收到目标主机B的确认后要向目标主机B给出确认,其
ACK
置1,确认号为y +1
,而自己的序号为x + 1
,A进入ESTABLISHED状态
,B收到报文后也进入ESTABLISHED
状态
- 主动建立连接方A的TCP向主机B发出连接请求报文段,其首部中的
-
四次挥手过程
- 主动关闭主机A的应用进程先向其TCP发出连接释放请求,并且不再发送数据。TCP通知对方要释放从A到B这个方向的连接,将发往主机B的TCP报文段首部的终止比特
FIN
置1,其序号x等于前面已传送过的数据的最后一个字节的序号加1 - 被动关闭主机B的TCP收到释放连接通知后即发出确认,其序号为
y
,确认号为x + 1
,同时通知高层应用进程,这样,从A到B的连接就释放了,连接处于半关闭状态。但若主机B还有一些数据要发送主机A,则可以继续发送。主机A只要正确收到数据,仍应向主机B发送确认 - 若主机B不再向主机A发送数据,其应用进程就通知TCP释放连接。主机B发出的连接释放报文段必须将终止位
FIN
和确认位ACK
置1,并使其序号仍为y
,但还必须重复上次已发送过的ACK
=x + 1
- 主机A必须对此发出确认,将
ACK
置1,ACK
=y + 1
,而自己的序号是x + 1
。这样才把从B到A的反方向的连接释放掉。主机A的TCP再向其应用进程报告,整个连接已经全部释放
- 主动关闭主机A的应用进程先向其TCP发出连接释放请求,并且不再发送数据。TCP通知对方要释放从A到B这个方向的连接,将发往主机B的TCP报文段首部的终止比特
-
为什么要三次握手?两次不行吗?
- 三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的
- 经典场景:客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了
- 由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接
- 此时此前滞留的那一次请求连接,网络通畅了到达服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费
- 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接
- 避免资源浪费
- 如果客户端的
SYN
阻塞了,重复发送多次SYN
报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费
- 如果客户端的
-
TCP三次握手中,最后一次回复丢失,会发生什么?
- 如果最后一次ACK在网络中丢失,那么Server端(服务端)该TCP连接的状态仍为SYN_RECV,并且根据 TCP的超时重传机制依次等待3秒、6秒、12秒后重新发送 SYN+ACK 包,以便 Client(客户端)重新发送ACK包
- 如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server(服务端)自动关闭这个连接 。当失败时服务器并不会重传ack报文,而是直接发送RTS报文段,进入CLOSED状态。这样做的目的是为了
防止SYN洪泛攻击
- 但是Client(客户端)认为这个连接已经建立,如果Client(客户端])端向Server(服务端)发送数据,Server端(服务端)将以RST包(Reset,标示复位,用于异常的关闭连接)响应,此时,客户端知道第三次握手失败
-
TCP是如何保证可靠传输的?
- 三次握手建立连接(标志位):通信前确认通信实体存在,并且双方可以正确发送和接收对方的信息
- 序号机制(序号、确认号):确保了数据是按序、完整到达
- 数据校验(校验和):CRC校验全部数据,保证数据完整性和正确性
- 超时重传(定时器):保证因链路故障未能到达数据能够被多次重发
- 窗口机制(窗口):提供流量控制,避免过量发送
- 拥塞控制:使用拥塞窗口机制,控制发送窗口大小,减少网络拥塞,避免因网络拥塞导致频繁丢包
-
为什么TCP挥手每两次中间有一个 FIN-WAIT2等待时间?
- 主动关闭的一端调用完close以后(即发FIN给被动关闭的一端, 并且收到其对FIN的确认ACK)则进入FIN_WAIT_2状态。如果这个时候因为网络突然断掉、被动关闭的一段宕机等原因,导致主动关闭的一端不能收到被动关闭的一端发来的FIN(防止对端不发送关闭连接的FIN包给本端),这个时候就需要FIN_WAIT_2定时器, 如果在该定时器超时的时候,还是没收到被动关闭一端发来的FIN,那么直接释放这个链接,进入CLOSE状态
-
为什么客户端最后还要等待2MSL?/为什么还有个TIME-WAIT的时间等待?
- 保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,服务器已经发送了FIN+ACK报文,请求断开,客户端却没有回应,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器
- 防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段(被动关闭方延时到来的FIN报文)都从网络中消失(指的是在路由器的缓存失效),这样新的连接中不会出现旧连接的请求报文
- 2MSL,最大报文生存时间,一个MSL 60 秒,2MSL = 120s
-
TIME-WAIT 状态过多会产生什么后果?怎样处理?
- 在高并发短连接的TCP服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败
- 作为服务器,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,