细说TCP

659 阅读10分钟

TCP和UDP都是传输层协议,负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题。传输层使用16比特位(0~65535)表示的端口标记不同的网络进程。

1663038090094.png

UDP协议(User Datagram Protocol,用户数据报协议) 其特点:

  • UDP是无连接协议;
  • UDP不能保证可靠的交付数据;
  • UDP是面向报文传输的;
  • UDP没有拥塞控制;
  • UDP首部开销很小。

TCP协议(Transmission Control Protocol,传输控制协议) 其特性如下:

  • TCP是面向连接的协议;
  • TCP是面向字节流的协议;
  • TCP的一个连接有两端,即点对点通信;
  • TCP提供可靠的传输服务;
  • TCP协议提供全双工通信(每条TCP连接只能一对一);

该协议功能有

  • 对应用层报文进行分段和重组;
  • 面向应用层实现复用与分解;
  • 使用滑动窗口实现端到端的流量控制;
  • 利用慢启动算法+拥塞避免算法实现拥塞控制;
  • 传输层寻址;
  • 对收到的报文进行差错检测(首部和数据部分都检错);
  • 实现进程间的端到端可靠数据传输控制。

拥塞控制 vs 流量控制

流量控制主要是控制点对点的通信量,而拥塞控制则是考虑整个网络,是全局性的考虑。

不可靠传输信道在数据传输过程可能发生:比特差错,乱序,重传,丢失等情况,故而TCP实现可靠传输的原理是基于不可靠信道实现可靠数据传输采取对应的措施,基于连续ARQ(Automatic Repeat reQuest:自动重传协议)即滑动窗口+累计确认,大幅提高了信道的利用率。

  • 差错检测:利用编码实现数据包传输过程中的比特差错检测
  • 确认:接收方向发送方反馈接收状态
  • 重传:发送方重新发送接收方没有正确接收的数据
  • 序号:确保数据按序提交
  • 计时器:解决数据丢失问题

TCP三次握手 image.png

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,向客户端发送确认包ACK(x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,三次握手完成,客户端和服务器进入ESTABLISHED(TCP连接成功)状态。

TCP四次挥手

image.png

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。

TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4)服务器将最后的数据发送完毕后,则向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

握手三次却需要四次挥手的原因:

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,服务端可能有数据还未发送完毕,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,等到服务端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送。故需要四步握手。

TIME_WAIT状态需要经过2MSL才能返回CLOSE状态的原因:

因为客户端发送ACK包确认服务端的FIN包时,有可能发生丢包,导致服务端没有收到ACK包,不断的重传FIN。所以客户端不能立即关闭,必须确认服务端已经收到了ack,所以客户设置了一个计时器,进入TIME_WAIT状态,等待2MSL(即一个发送和一个回复所需的最大时间)。2MSL时间内没有再次收到服务端的FIN包,则确认ACK已被成功接收,进入关闭状态。

需要三次握手而不是两次的原因:

主要是为了防止已失效的连接请求报文段突然又传送到服务端,因而产生错误。 客户端发出连接请求,但因连接请求报文丢失而未收到确认,故客户端又重传一次,且成功收到服务端的确认包,建立了连接,数据传输完毕后,释放连接。在这个过程中,客户端共发送了两个请求连接的报文,第一个没有收到服务端的确认,有可能并不是丢失,而是在某些网络节点滞留时间太长,导致客户端误以为数据丢失,重传数据。因此当第一个请求报文到达服务端时,服务端误以为客户端又发出一次新的连接请求,于是向客户端发送确认报文,同意建立连接但客户端并没有要求建立连接也没有向服务端发送数据,而服务端一直处于等待数据接收状态,造成服务端资源的浪费。因此三次握手可以避免上述情况的发送,只要服务端没有收到客户端的确认包就不建立连接。

拔掉网线后,TCP连接是否断开?

客户端拔掉网线后,并不会直接影响 TCP 连接状态。所以,拔掉网线后,TCP 连接是否还会存在,关键要看拔掉网线之后,有没有进行数据传输。

有数据传输的情况:

  • 在客户端拔掉网线后,如果服务端发送了数据报文,那么在服务端重传次数没有达到最大值之前,客户端就插回了网线,那么双方原本的 TCP 连接还是能正常存在,就好像什么事情都没有发生。
  • 在客户端拔掉网线后,如果服务端发送了数据报文,在客户端插回网线之前,服务端重传次数达到了最大值时,服务端就会断开 TCP 连接。等到客户端插回网线后,向服务端发送了数据,因为服务端已经断开了与客户端相同四元组的 TCP 连接,所以就会回 RST 报文,客户端收到后就会断开 TCP 连接。至此, 双方的 TCP 连接都断开了。

没有数据传输的情况:

  • 如果双方都没有开启 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,那么客户端和服务端的 TCP 连接状态将会一直保持存在。
  • 如果双方都开启了 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,TCP keepalive 机制会探测到对方的 TCP 连接没有存活,于是就会断开 TCP 连接。而如果在 TCP 探测期间,客户端插回了网线,那么双方原本的 TCP 连接还是能正常存在。

除了客户端拔掉网线的场景,还有客户端「宕机和杀死进程」的两种场景。

第一个场景,客户端宕机这件事跟拔掉网线是一样无法被服务端的感知的,所以如果在没有数据传输,并且没有开启 TCP keepalive 机制时,,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。

所以,我们可以得知一个点。在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。

第二个场景,杀死客户端的进程后,客户端的内核就会向服务端发送 FIN 报文,与客户端进行四次挥手。

所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。

TCP的缺陷:

  1. 升级TCP的工作困难,因为TCP协议是在内核中实现的,应用程序只能调用不可修改
  2. TCP建立连接有延迟,基于TCP实现的应用协议都需要先建立三次握手才能进行数据传输,如HTTPS是基于HTTP加上SSL/TSL,所以其TCP三次握手后还需要TSL/SSL四次握手才能进行数据传输,在一定程度上增加了数据传输的延迟
  3. HTTP/2 存在队头阻塞问题,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且有序的,如果序列号较低的 TCP 段在网络传输中丢失了,即使序列号较高的 TCP 段已经被接收了,应用层也无法从内核中读取到这部分数据,只有等到低序列号的数据包被接收才能继续读取
  4. 网络迁移需要重新建立TCP连接,基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接,当移动设备的网络从4G切换到WIFI时,意味着IP地址变化了,那么就必须要断开连接,然后重新建立 TCP 连接。

TCP三次握手和TSL握手延迟

TCP+TSL握手.jpg

总结

TCP传输数据稳定可靠,适用于对网络通讯质量要求较高的场景。如:文件传输,邮件发送,网页浏览等,UDP的优点则是快速,由于不可靠,可能产生丢包,所以适用于对实时性要求较高但允许少量丢包的场景。如:域名解析,语音通话,视频直播,隧道网络VXLAN等。

参考链接:

blog.csdn.net/qq_38950316… mp.weixin.qq.com/s/RQwxAUsEg… mp.weixin.qq.com/s/UthSIyspW…