TCP知识
一、概要
TCP协议是有连接的,可靠性传输,全双工,面向字节流的传输层协议, 使用TCP协议在客户端和发送端传输数据前,必须先建立连接,传输数据完成之后,就要断开连接
二、过程
1. 握手
为什么需要三次握手才能建立连接?
- 为了初始化Sequence Number 的初始值,实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认
第三次可以携带数据吗?
可以。能够发出第三次握手报文的主机,肯定接收到第二次(服务器)握手报文,因为伪造IP的主机是不会接收到第二次报文的。
除了第一个握手报文SYN除外,其它所有报文必须将ACK = 1?
TCP作为一个可靠传输协议,其可靠性就是依赖于收到对方的数据,ACK对方,这样对方就可以释放缓存的数据,因为对方确信数据已经被接收到了。
但TCP报文是在IP网络上传输,丢包是家常便饭,接收方要抓住一切的机会,把消息告诉发送方。最方便的方式就是,任何我方发送的TCP报文,都要捎带着ACK状态位。
为什么是三次不是两次?
防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
TCP 长连接和短连接有什么区别?
TCP 短连接的优点在于管理简单,而且不会对服务端造成太大的压力,而缺点是每次读写都需要连接耗时较长。
TCP 长连接的优点是可以迅速进行多次读写,缺点是对服务端压力大,且容易被恶意连接影响服务。
TCP 通过哪些方式来保证数据的可靠性?
1、在数据包层面:校验和
2、在数据包传输层面:序列号、确认应答、超时重传
3、在流量控制层面:拥塞控制
2. 挥手
-
客户端进程发出连接释放报文
,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态
。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。 -
服务器收到连接释放报文,发出确认报文
,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态
。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。 - 客户端收到服务器的确认请求后,此时,
客户端就进入FIN-WAIT-2(终止等待2)状态
,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最 后的数据)。 -
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文
,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态
,等待客户端的确认。 -
客户端收到服务器的连接释放报文后,必须发出确认
,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态
。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
。 - 服务器只要收到了客户端发出的确认,
立即进入CLOSED状态
。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些
。
为什么挥手需要四次?
半关闭(half-close)特性,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力
挥手报文丢失会发生什么?
第一次挥手丢失
如果客户端一直收不到ack应答报文的话,就会触发超时重传机制,最大重传次数由tcp_orphan_retries参数决定。当超过指定次数时,就不再发送报文,直接进入close状态
第二次挥手丢失
当ack报文丢失时,ack是不会重传的。服务端的ack报文丢失了,客户端就会触发超时重传,直到收到ack报文或则到达超时重传次数。
第三次挥手丢失
内核就会发出FIN报文,进入LAST_ACK状态,等待客户端返回ack来确认关闭连接。如果服务端没有收到ack,则会跟客户端重传FIN报文一样
第四次挥手丢失
如果服务端没有收到ack报文的话,服务端就会重发FIN报文,重发次数仍然由tcp_orphan_retries参数控制
为什么需要TIME_WAIT状态?
防止错误接收历史报文
:tcp序列号可能会发生绕回问题,这就意味着无法通过tcp序列号来判断是不是历史报文
保证双方能够正常关闭
:如果服务端没有收到ack报文的话,就会重传FIN报文,而此时客户端已经close了,就会返回一个RST错误报文。
如果已经建立了连接,但是另一端突然出现故障,会发生什么?
TCP有保活机制:当一端时间相互直接没有发送数据时,就会触发保活机制。即每隔一段时间都发送一次探测报文给对方,如果几次都不回应的话,就会认为对方已经死亡了,那么就会断开连接。
*应用层心跳机制:*web服务一般都会提供time_keeplive参数,用来指定http长连接超时时间。
TCP的粘包和拆包
TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。
为什么会产生粘包和拆包呢?
- 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
- 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
- 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。
解决方案:
- 发送端将每个数据包封装为固定长度
- 在数据尾部增加特殊字符进行分割
- 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小。
TCP的KeepAlive
交互双方都有可能出现掉电、死机、异常重启等各种意外,连接的另一方并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费TCP, KeepAlive 的基本原理是,隔一段时间给连接对端发送一个探测包,如果收到对方回应的 ACK,则认为连接还是存活的,在超过一定重试次数之后还是没有收到对方的回应,则丢弃该 TCP 连接。
三、优缺点
优点
可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。文章来源:https://www.toymoban.com/news/detail-804616.html
缺点
慢,效率低,占用系统资源高,易被攻击TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。文章来源地址https://www.toymoban.com/news/detail-804616.html
在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输 …………
什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP
到了这里,关于TCP 常见问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!