TCP和UDP
两者之间的区别
- tcp向上层面向连接的可靠服务,udp向上层提供无连接的不可靠服务。所谓面向连接,功夫不在链路,在客户端和服务端各自维护了一套状态机,记录和维护连接的状态,通过三次握手建立连接,四次挥手断开连接,彼此可以感受到对方的存在,在计算机两端表现为socket。在IP层,网络情况该不稳定还是不稳定,数据传输层走的什么路径,上层是控制不了的,tcp能做的是更多判断,更多重试,更多拥塞控制之类的东西。
- tcp是有状态的服务,有发送缓存和接收缓存,精确地记录着发送了没有,接收了没有,发送到哪了,接收到哪了,错一点就不行。udp是无状态的,发了就发了。
- udp并没有tcp传输准确,但是在很多实时性要求较高的地方有所作为,对数据准确性高,速度可以相对较慢的,可以选用tcp。
UDP适用场景
- 基于udp改造的 QUIC协议,在应用层上,实现连接快速建立,较少重传时间,自适应拥塞控制。
- 流媒体协议,直播应用基于udp实现了自己的传输协议。
- 实时游戏
- IOT物联网
TCP握手、挥手过程
握手过程
握手前,服务端创建socket对象,绑定地址(ip和端口),开启监听(调用listen);客户端创建socket,准备连接(connect)。然后进行三次握手连接:
- client向server发送一个
SYN包,seq=x; - server接收到
SYN包之后,向client发送SYN ACK,seq=y,ack=x+1; - client接收到server的
SYN ACK之后,再向server端发送ACK,ack=y+1包,至此三次握手完成。
为什么是三次而不是四次? 1. 第二次握手的时候,server把 ACK和SYN 一起发送了; 2. 四次也是可以的,四十次也可以,关键是不能保证真的就可靠了,**只要双方的消息都有去有回**,就可以了。
为什么不是两次?
- server端可能会存在很多创建好的连接对象,但是并没有使用,浪费资源。
三次握手除了双方建立连接之外,主要还是为了沟通一件事,TCP包的序号问题。
挥手过程
断开tcp需要四步,断开连接可以是client主动,server被动,也可以是server主动断开。这两种的状态变化也是相对的。以client主动断开为例子:
- client发送 FIN 包,表示要断开 client 到 server的连接;
- server收到 FIN 之后,发送一个 ACK 包,表示确定断开连接;
- 同时,server也会再发送一个 FIN 包,表示想断开 server 到 client 的连接;
- client收到server的 ACK 包,确定了client->server的连接断开,该连接不会发送数据;
- 由于client也受到了server的FIN包,因此也要断开server->client的连接,发送ACK给server确定。
拥塞控制和流量控制
流量控制
- 流量控制的目的
发送方发送数据太快,接收方来不及接收,就会有分组丢失,为了避免分组丢失,控制发送者的发送速度,让接受者来得及接收。根本目的时,别发的太快,让接收方撑死,也别发的太慢让接收方饿死。
- 实现流量控制
滑动窗口协议,连续ARQ协议,保证了分组无差错、有序接收,累计ack,也实现了流量控制。主要方式,接收方返回的ack中包含自己的接收窗口大小,并且利用大小来控制发送方的数据发送。
- 流量控制引发的死锁?如何避免?
当发送方接收到一个窗口为0的ack,发送者停止发送,等待下一个ack,但是如果下一个ack的窗口不为0,但是在传输过程中丢失,发送者就一直等待下去,接受者也认为发送者已经收到这个丢失的ack,等待接收新数据,双方互相等待,导致了死锁的发生。 tcp采用了持续计时器,每当发送者收到一个窗口大小为0的ack后之后,就启动计时器,时间到了就会主动发送报文询问接受者的窗口大小,如果接收者仍返回0,则重置继续等待;窗口不为0,那拿到新的窗口大小就可以继续开始发送。从发送方,打破了循环等待导致的死锁。
拥塞控制
- 和流量控制的区别
流量控制:作用于接受者,控制发送者的发送速度从而使接受者来得及接收,防止分组丢失。累计ack解决顺序问题和丢包问题。
拥塞控制:作用于网络,避免包丢失和超时重传,防止太多的数据注入网络,避免网络负载过大。常用方法:(1)慢开始、拥塞避免; (2)快重传、快恢复。
- 拥塞控制算法
假定不考虑流量控制的情况,1、数据是单方向传递,另一个窗口只发送确认;2、接收方的缓存足够大,因此发送方的大小的大小由网络的拥塞程度来决定。
慢开始算法:
发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。
慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
这里用报文段的个数作为拥塞窗口的大小举例说明慢开始算法,实际的拥塞窗口大小是以字节为单位的。
从上图可以看到,一个传输轮次所经历的时间其实就是往返时间RTT,而且没经过一个传输轮次(transmission round),拥塞窗口cwnd就加倍。
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下: 当cwnd<ssthresh时,使用慢开始算法。 当cwnd>ssthresh时,改用拥塞避免算法。 当cwnd=ssthresh时,慢开始与拥塞避免算法任意
注意,这里的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,然后逐渐增大,这当然比按照大的cwnd一下子把许多报文段突然注入到网络中要“慢得多”。
拥塞避免算法:
拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口按线性规律缓慢增长。
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
(1)拥塞窗口cwnd初始化为1个报文段,慢开始门限初始值为16 (2)执行慢开始算法,指数规律增长到第4轮,即cwnd=16=ssthresh,改为执行拥塞避免算法,拥塞窗口按线性规律增长 (3)假定cwnd=24时,网络出现超时(拥塞),则更新后的ssthresh=12,cwnd重新设置为1,并执行慢开始算法。当cwnd=12=ssthresh时,改为执行拥塞避免算法
关于 乘法减小(Multiplicative Decrease)和加法增大(Additive Increase):
“乘法减小”指的是无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半,并执行慢开始算法,所以当网络频繁出现拥塞时,ssthresh下降的很快,以大大减少注入到网络中的分组数。“加法增大”是指执行拥塞避免算法后,使拥塞窗口缓慢增大,以防止过早出现拥塞。常合起来成为AIMD算法。
注意:“拥塞避免”并非完全能够避免了阻塞,而是使网络比较不容易出现拥塞。
快重传算法:
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认。
快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
快恢复算法:
快重传配合使用的还有快恢复算法,有以下两个要点:
当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半(为了预防网络发生拥塞)。但是接下去并不执行慢开始算法。
考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh减半后的值,然后执行拥塞避免算法,使cwnd缓慢增大。如下图:TCP Reno版本是目前使用最广泛的版本。
注意:在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用。
HTTP
http长连接和短连接问题
-
http长连接和短连接的使用场景
-
如何支持http长连接
-
tcp的keep-alive和http的keep-alive的区别 一般建立起连接后,client和server会发送数据,但是client就是不发数据,建立连接后空着,但是如果没有真实的数据包,也会有探活包,keepalive机制。
httpclinet和mysql的Timeout设置
1.connection timeout和socket timeout的区别
2.线上如何设置connection timeout和sokcet timeout的值
3.TIME_WAIT和CLOSE_WAIT的作用