1 TCP三次握手、四次挥手
2 TCP滑动窗口机制
image.png
- 客户端不断快速发送数据,服务器接收相对较慢,看下实验的结果
a. 包175,发送ACK携带WIN = 384,告知客户端,现在只能接收384个字节
b. 包176,客户端果真只发送了384个字节,Wireshark也比较智能,也宣告TCP Window Full
c. 包177,服务器回复一个ACK,并通告窗口为0,说明接收方已经收到所有数据,并保存到缓冲区,但是这个时候应用程序并没有接收这些数据,导致缓冲区没有更多的空间,故通告窗口为0, 这也就是所谓的零窗口,零窗口期间,发送方停止发送数据
d. 客户端察觉到窗口为0,则不再发送数据给接收方
e. 包178,接收方发送一个窗口通告,告知发送方已经有接收数据的能力了,可以发送数据包了
f. 包179,收到窗口通告之后,就发送缓冲区内的数据了.
3 TCP拥塞控制机制
拥塞控制的算法有:慢开始、拥塞避免、快重传、快恢复四种。
拥塞的标志:重传计时器超时、接收到三个重复确认。
控制机制:
image.png
image.png
快重传:
image.png
面试题:
腾讯面试题
TCP的拥塞控制机制是什么?请简单说说。
答:我们知道TCP通过一个定时器(timer)采样了RTT并计算RTO,但是,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,然而重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这就导致了恶性循环,最终形成“网络风暴” —— TCP的拥塞控制机制就是用于应对这种情况。
首先需要了解一个概念,为了在发送端调节所要发送的数据量,定义了一个“拥塞窗口”(Congestion Window),在发送数据时,将拥塞窗口的大小与接收端ack的窗口大小做比较,取较小者作为发送数据量的上限。
拥塞控制主要是四个算法:
1.慢启动:意思是刚刚加入网络的连接,一点一点地提速,不要一上来就把路占满。
连接建好的开始先初始化cwnd = 1,表明可以传一个MSS大小的数据。
每当收到一个ACK,cwnd++; 呈线性上升
每当过了一个RTT,cwnd = cwnd*2; 呈指数让升
阈值ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”
2.拥塞避免:当拥塞窗口 cwnd 达到一个阈值时,窗口大小不再呈指数上升,而是以线性上升,避免增长过快导致网络拥塞。
每当收到一个ACK,cwnd = cwnd + 1/cwnd
每当过了一个RTT,cwnd = cwnd + 1
拥塞发生:当发生丢包进行数据包重传时,表示网络已经拥塞。分两种情况进行处理:
等到RTO超时,重传数据包
sshthresh = cwnd /2
cwnd 重置为 1
3.进入慢启动过程
在收到3个duplicate ACK时就开启重传,而不用等到RTO超时
sshthresh = cwnd = cwnd /2
进入快速恢复算法——Fast Recovery
4.快速恢复:至少收到了3个Duplicated Acks,说明网络也不那么糟糕,可以快速恢复。
cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
重传Duplicated ACKs指定的数据包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了。
4 socket模型
image.png
套接字的几个函数对应的TCP操作
image.png
socket
创建套接字,指定要使用的地址簇(ip)和套接字类型/传输层协议(tcp),返回一个套接字描述符,简称sockfd,用于在函数调用(connect、read 等)中标识这个套接字。
bind
将一个 本地IP:本地端口 赋值给一个套接字,限定该套接字只接收目的地为指定的本地IP、端口的客户连接。进程指定。
linsen
仅由 TCP server 调用。当 socket 函数创建了套接字,会假设为主动套接字,也就是将调用 connect 主动发起连接的套接字。linsen 将一个未连接的套接字转换成被动套接字,通知内核应该接受指向该套接字的连接请求(被动打开)。此时套接字的状态从 CLOSED 转到 LISTEN。
内核为每个监听套接字维护两个队列:
未完成连接队列,收到了客户的 SYN,正在等待 TCP 三次握手完成。此时套接字的状态为 SYN_RCVD。
已完成连接队列,已经完成 TCP 三次握手的客户,这些套接字处于 ESTABLISHED 状态。
当收到客户的SYN,TCP在未完成连接队列中创建一项新条目,同时继承监听套接字的参数,然后返回SYS、ACK,这一项一直保留在未完成连接队列中,直到收到 ACK,或者该项超时。如果三次握手正常完成,该项从未完成连接队列移到已完成连接队列的队尾。
指定 backlog,即两个队列长度之和。
image.png
accept
仅由 TCP server 调用,从已完成连接的队头获得一个已完成连接,如果已完成连接的队列为空,进程被挂起进入睡眠状态(假定套接字为默认的阻塞方式),直到队列中有条目。
接收监听套接字描述符,返回 由内核自动为获得的已完成连接生成的已连接套接字描述符,以及对应的已连接套接字。
connect
仅由 TCP client 调用,接收 socket 返回的套接字描述符,主动向 TCP server 发送建立连接的请求(主动打开),触发三次握手。调用 connect 之前不一定要调用 bind 绑定本地ip 和 本地端口,这样,内核会通过数据出口确定源ip,并选定一个临时端口作为源端口。
- TCP UDP区别
1、基于连接与无连接;
2、对系统资源的要求(TCP较多,UDP少);
3、UDP程序结构较简单;
4、流模式与数据报模式 ;
5、TCP保证数据正确性,UDP可能丢包;
6、TCP保证数据顺序,UDP不保证。 - Time_Wait中2*msl 为什么
如果TIME_WAIT状态保持时间不足够长,第一个连接就正常终止了。第二个拥有相同五元组的连接出现,而第一个连接的重复报文到达,干扰了第二个连接。TCP事先必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT状态保持时间足够长(2MSL),连接相应方向的上的TCP报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不会混淆。 - 一个url从输入到访问经过了哪些过程
1.DNS 解析:将域名解析成 IP 地址
2.TCP 连接:TCP 三次握手
3.发送 HTTP 请求
4.服务器处理请求并返回 HTTP 报文
5.浏览器解析渲染页面
6.断开连接:TCP 四次挥手
网友评论