1、TCP和UDP的区别
传输方式:TCP是面向连接的,UDP是面向无连接的,所谓连接是一个逻辑上的概念,TCP需要在两端都建立数据结构来保存对端的通信状态,以此达到维持连接的目的;
传输实体:TCP面向字节流(将包看成字节流,把字节流组织成数据块),UDP面向的是报文包;
传输控制:TCP提供流量控制机制,可以限制对端流量的传输,UDP不提供;
可靠性:TCP提供可靠传输保证,UDP属于尽力而为方式;
网络治理:TCP提供拥塞控制机制,可以缓解网络链路的拥塞情况,UDP不提供;
连接对象:TCP只能提供点到点的连接(一对一),UDP可以提供一对一、一对多、多对一、多对多;
首部占用:TCP头部占用为20~60字节,UDP头部占用为8字节(4个字段);
TCP提供了保障机制,在连接状态更迭中需要三握四挥,因此并不适用于实时应用,比如视频聊天、语音聊天等场景一般采用UDP传输。
2、三次握手
两次握手行不行?
①两次握手完成后服务端只清楚客户端的发送能力没问题,自己的接受能力没问题,但还不清楚客户端的接受能力是否可行,也不清楚自己的发送能力是否可行;
②两次握手时可能存在延期到达报文包,这些包是客户端重传之前发送的,如果只是两次握手建立连接,那么服务端收到这些过期包会发送确认包之后进入established状态,而如果客户端此时已经离线,那么肯定收不到回复,服务端就浪费了等待的时间;
第三次握手丢包怎么办?
① 对于服务端来说,它在收不到第三次握手的包后会触发超时重传机制,之后每隔2s 4s 8s 重新发送第二次握手的包,如果在达到阈值之前都没有收到回复,就会关闭连接;
② 对于客户端来说,此时它已经进入established状态,会开始发送数据包,如果第三次握手包没到达,那么客户端会收到服务端的带有RST标志的回复,表明连接异常中断了,之后客户端尝试重连。
3、四次挥手
这里需要注意,RFC793明确规定,除了第一个握手报文SYN除外,其它所有报文必须将ACK = 1。上图第一次挥手和第三次挥手省略了这两个部分,单凭ACK是不能确定成功接收的,还需要有ack码来确认成功接收多少数据。
为什么要四次挥手,三次挥手行不行?
第一次挥手是客户端主动发起的断开连接请求,第二次挥手服务端回复一个ACK代表同意客户端断开到服务端的连接;同意归同意,服务端可能还有数据没发完,这时候需要有application决定是否断开服务端到客户端的连接,如果只是三次挥手,那么这些还没发送的数据就丢失了,因此需要等服务端把要发的数据全部发送完毕,再进行第三次挥手,发送FIN代表我这边也可以了,接着第四次挥手客户端回复ACK,服务端收到之后就可以关闭连接了。
三次挥手的情况可能也会存在,主要原因是第二和第三次挥手合并了,也即是application没有数据发送了,可以直接FIN-ACK联合发送过去(延迟确认)。
为什么在Time-Wait阶段需要等待2MSL?
首先明确,MSL是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
那么等待2MSL有两个主要原因,一个是客户端发送ACK之后并不确定对端是否接受到了,客户端发送的包可能会丢失,如果ACK丢失或者是延迟了,那么服务端就会重发一个FIN包,这时客户端的计时器会重新计时2MSL;如果没有丢失他需要等待多少时间才能确定自己的包成功发送了呢?这里就有个等待的时间研判,2MSL代表的是数据包一来一回的时间(去向ACK消息最大存活时间 来向FIN消息的最大存活时间),如果数据包没丢失,那么在2MSL时间内是不会再收到服务端的重发包的,这时客户端就可以安心关闭连接了;
另一个原因,在数据传输的过程中,可能会有重发的数据包还在网络中游离,这时候等待一段时间可以让那些游离的数据包被接受-丢弃,而不会影响下一次同IP-同端口的连接。
Time-Wait过多会造成什么问题?
一个是内存占用过多,一个是端口资源消耗过多。首先端口资源是有限的,如果一直持续在Time-Wait阶段,那么连接无法释放,端口也就无法被复用,这样的连接多了,势必造成端口耗尽的危险。其次,服务端监听的端口确实只有一个,但是来新的连接会创建其他端口连接,如果这些连接一直保持在Time-Wait阶段,那么势必造成资源的耗尽,无法处理其他连接资源。
如果客户端没有四次挥手就断开了,服务端怎么办?
TCP利用计时器 超时重试实现了保活机制,服务端会维护一个计时器,每当收到客户端的包时就重新计数,如果达到计数阈值(Linux一般为2小时),就会触发超时重试,每75秒发送一个探测报文包(一般会很小),如果重发十次都没有收到回复,那么服务端会研判客户端已经异常断开了,这时候他就会断开他们的连接。