1.TCP和UDP的区别是什么?
- TCP和UDP都是属于运输层的,是两种在程序之间传输数据的通信协议;
- 可以感性地把UDP理解为写信,TCP理解为打电话;
- TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接;
- TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付;
- TCP面向字节流,实际上TCP把数据看成一连串无结构的字节流;UDP是面向报文的;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等);
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对多的交互通信;
- TCP首部开销20字节;UDP的首部开销小,只有8个字节;
- TCP的逻辑通信是全双工的可靠信道,UDP则是不可靠信道。
追问1:TCP和UDP的使用场景?
- 某些情况下UDP确是一种最有效的工作方式(一般用于即时通信),比如:QQ语音、QQ视频、直播等对实时性要求较高的场景;
- TCP一般用于文件传输、发送和接受邮件、远程登录等场景。
2.TCP是如何保证可靠传输的?
- 应用数据被分割成TCP认为最合适发送的数据块。
- TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
- 校验和:TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。
- TCP的接收端会丢弃重复的数据。
- 流量控制:TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能够接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。(TCP利用滑动窗口实现流量控制)
- 拥塞控制:当网络拥塞时,减少数据的发送。
- ARQ协议:也是为了实现可靠传输的,它的基本原理就是每发送完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
- 超时重传:当TCP发出一个段后,它将启动一个定时器,等待接收端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
3.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状态。
四次挥手
- 四次挥手本质上是为了保证在不可靠的网络连接中,进行可靠的连接断开。
- 四次挥手的过程:
- 客户端打算关闭连接,此时会发送一个TCP首部FIN标志位置为1的报文,也即FIN报文,之后客户端进入FIN_WAIT_1状态;
- 服务端收到该FIN报文之后,就向客户端发送ACK应答报文,接着服务端进入CLOSED_WAIT状态。
- 客户端收到服务端的ACK应答报文后,之后进入FIN_WAIT_2状态;
- 等待服务端处理完数据后,也向客户端发送FIN报文,之后服务端进入LAST_ACK状态;
- 客户端收到服务端的FIN报文后,回一个ACK应答报文,之后进入TIME-WAIT状态
- 服务器收到ACK应答报文之后,就进入了CLOSED状态,至此服务端已经完成连接的关闭。
- 客户端在经过2MSL一段时间后,自动进入CLOSED状态,至此客户端也完成了连接的关闭。(注意:主动关闭连接的,才有TIME-WAIT状态)
追问1:为什么是三次?不是两次、四次?
- “因为三次才能保证双方具有接收和发送的能力。”
- TCP建立连接时,通过三次握手能防止历史连接的建立,能够减少双方不必要的资源开销,能够帮助双方同步初始化序列号。序列号能够保证数据包不重复,不丢弃和按序传输。
不使用两次和四次的原因:
- 两次:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
- 四次:三次握手就已经是理论上最少步数的可靠连接建立方法,所以不需要再使用更多的通信次数。
追问2: 为什么TIME_WAIT的等待时间是2MSL?
- MSL:报文最大生存时间,是指任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因TCP报文基于IP协议,而IP头中有一个TTL字段,是IP数据报可以经过的最大路由数,每经过一个处理他的路由器,此值就减少1,当此值为0时则数据将被丢弃,同时发送ICMP报文通知源主机。
- MSL与TTL的区别:MSL的单位是时间,而TTL是经过路由跳数。所以MSL应该要大于等于TTL消耗为0的时间,以确保报文自然消亡。
- 2MSL的时间是从客户端收到FIN后发送ACK开始计时的。如果在TIME-WATI时间内,因为客户端的ACK没有传输到服务端,客户端又接收到了服务端重发的FIN报文,那么2MSL时间将重新计时。
- Linux系统里2MSL默认是60秒。
追问3: 为什么需要TIME_WAIT状态?
主要两个原因:
- 防止具有相同‘四元组’的‘旧’数据包被收到;
- 保证‘被动关闭连接’的一方能够被正确关闭,即保证最后的ACK能让被动关闭的一方接收,从而保证其正常关闭。
追问4: TIME_WAIT过多有什么危害?
- 第一是内存资源占用;
- 第二是端口资源占用,一个TCP连接至少消耗一个本地端口。
4.拥塞控制有哪些控制算法?
- 慢启动
- 拥塞避免
- 拥塞发生
- 快速恢复
5.TCP半连接队列和全连接队列。
在TCP三次握手的时候,Linux内核会维护两个队列,分别是
- 半连接队列,也称SYN队列
- 全连接队列,也称accept队列
- 服务端收到客户端发起的SYN请求后,内核会把该连接存储到半连接队列,并向客户端响应SYN+ACK,接着客户端会返回ACK,服务端收到第三次握手的ACK后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到accept队列,等待进程调用accept函数时把连接取出来。
面试题:讲一下流量控制和拥塞控制,有了流量控制为什么还要拥塞控制?
- TCP协议提供流量控制(匹配源主机的发送数据速率与目的主机的接收数据速率,以防止目的主机溢出)、差错控制(保证数据段无差错到达目的地和重新发送受损的数据段)、拥塞控制(减少由于网络拥塞造成的数据段丢失)。
- 流量控制是对于源主机和目的主机的数据发送/接收速率匹配而言的;而拥塞控制是针对于网络拥塞的状况而言的。两者针对的情景不一致,但都是为了保证数据传输的可靠与稳定。