1、tcp协议的特点

TCP是在不可靠的IP层之上实现的可靠的数据传输协议,它主要解决传输的可靠、有序、无丢失和不重复问题。TCP 是TCP/IP 体系中非常复杂的一个协议,主要特点如下:

  • TCP 是面向连接的传输层协议。

  • 每条TCP 连接只能有两个端点,每条TCP 连接只能是点对点的(一对一)。

  • TCP 提供可靠的交付服务,保证传送的数据无差错、不丢失、不重复且有序。

    • 如何保证数据无差错、不丢失、不重复且有序的?有哪些机制来保证?

      答:TCP 使用了校验、序号、确认和重传等机制来达到这一目的。

  • TCP 提供全双工通信,允许通信双方的应用进程在任何时候都能发送数据,为此TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。

    • 为什么需要设置缓存,缓存的作用?

      答:发送缓存用来暂时存放以下数据:1.发送应用程序传送给发送方TCP 准备发送的数据;2.TCP已发送但尚未收到确认的数据。

      接收缓存用来暂时存放以下数据:1.按序到达但尚未被接收应用程序读取的数据;2.不按序到达的数据。

  • TCP是面向字节流的,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅视为一连串的无结构的字节流。

    • 一个字节占一个序号,每个报文段用第一个字节的序号来标识,例如,一报文段的序号字段值是301, 而携带的数据共有l00B, 表明本报文段的数据的最后一个字节的序号是400, 因此下一个报文段的数据序号应从401开始,也就是期望的下一个序号(确认号)。

2、tcp报文段格式

部分字段解释:

1) 序号字段(就是seq):序号字段的值指的是本报文段所发送的数据的第一个字节的序号。

2) 确认号字段(就是ack):是期望收到对方的下一个报文段的数据的第一个字节的序号。若确认号为N, 则表明到序号N-1为止的所有数据都已正确收到。(累积确认)

3) 确认位ACK:只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。TCP 规定,在连接建立后所有传送的报文段都必须把ACK置1。

4) 同步位SYN。同步SYN=1表示这是一个连接请求或连接接收报文。当SYN= 1, ACK=0 时,表明这是一个连接请求报文,对方若同意建立连接,则在响应报文中使用SYN= 1, ACK=1。即SYN=1表示这是一个连接请求或连接接收报文。

5) 终止位FIN (Finish) 。用来释放一个连接。FIN=1表明此报文段的发送方的数据已发送完毕了并要求释放传输连接。

3、tcp连接管理

TCP 是面向连接的协议,因此每个TCP 连接都有三个阶段:连接建立、数据传送和连接释放。TCP 连接的管理就是使运输连接的建立和释放都能正常进行。

在TCP 连接建立的过程中,要解决以下三个问题:

1) 要使每一方都能够确知对方的存在。

2) 要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项、时间戳选项及服务质量等)。

3) 能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配。

每条TCP 连接唯一地被通信两端的两个端点(即两个套接字)确定。 端口拼接到IP地址即为套接字,tcp的连接采用的是客户机/服务器方式,主动发起连接建立的应用进程称为客户机,而被动等待连接建立的应用进程称为服务器。

4、tcp连接的建立

1) 第一次握手:客户机的TCP首先向服务器的TCP发送一个连接请求报文段。这个特殊的报文段中不含应用层数据,其首部中的SYN标志位被置为1。另外,客户机会随机选择一个起始序号seq = x(连接请求报文不携带数据,但要消耗一个序号)。

2) 第二次握手:服务器的TCP 收到连接请求报文段后,如同意建立连接,就向客户机发回确认,并为该TCP连接分配TCP缓存和变量。在确认报文段中,SYN 和ACK 位都被置为1, 确认号字段的值为x+1,并且服务器随机产生起始序号seq= y( 确认报文不携带数据,但也要消耗一个序号)。确认报文段同样不包含应用层数据。

3) 第三次握手:当客户机收到确认报文段后,还要向服务器给出确认,并且也要给该连接分配缓存和变量。这个报文段的ACK 标志位被置1, 序号字段为x+1, 确认号字段ack=y+1。该报文段可以携带数据,若不携带数据则不消耗序号 http中的tcp连接的第三次握手的报文段中就捎带了客户对万维网文档的请求 。成功进行以上三步后,就建立了TCP 连接,接下来就可以传送应用层数据。TCP 提供的是全双工通信,因此通信双方的应用进程在任何时候都能发送数据。

【总结】

  • 1) SYN = 1,ACK = 0,seq = x;
  • 2) SYN = 1,ACK = 1,seq = y,ack = x+1;
  • 3) SYN = 0,ACK = 1,seq = x+1,ack=y+1。

5、tcp释放连接

1) 第一次握手:客户机打算关闭连接时,向其TCP发送一个连接释放报文段,并停止发送数据,主动关闭TCP 连接,该报文段的FIN 标志位被置1, seq= u, 它等于前面已传送过的数据的最后一个字节的序号加1 (FIN 报文段即使不携带数据,也要消耗一个序号)。TCP是全双工的,即可以想象为一条TCP 连接上有两条数据通路。发送FIN 报文时,发送FIN 的一端不能再发送数据,即关闭了其中一条数据通路,但对方还可以发送数据。

2) 第二次握手:服务器收到连接释放报文段后即发出确认,确认号是ack = u + 1, 而这个报文段自己的序号是v, 等千它前面已传送过的数据的最后一个字节的序号加1 。此时,从客户机到服务器这个方向的连接就释放了,TCP连接处千半关闭状态。但服务器若发送数据,客户机仍要接收,即从服务器到客户机这个方向的连接并未关闭。

3) 第三次握手:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时其发出FIN=1的连接释放报文段。

4) 第四次握手:客户机收到连接释放报文段后,必须发出确认。在确认报文段中,ACK字段被置为1, 确认号ack= w + 1, 序号seq= u + 1 。此时TCP连接还未释放,必须经过时间等待计时器设置的时间2MSL(最长报文段寿命)后,A才进入连接关闭状态。

【总结】

  • 1) FIN = 1,seq = u;

  • 2) ACK = 1,seq = v,ack = u+1;

  • 3) FIN = 1,ACK = 1,seq = w,ack =u+1;(确认第一次的u)

  • 4) ACK = 1,seq = u+1,ack = w+1。

question one : 什么是SYN洪泛攻击?(三次握手机制有什么问题?)

答:由于服务器端的资源是在完成第二次握手时分配的,而客户端的资源是在完成第三次握手时分配的,攻击者发送TCP的SYN报文段,SYN是TCP三次握手中的第一个数据包,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,也就是所谓的半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务了。

question two :为什么不采用“两次握手”建立连接呢?

答:这主要是为了防止两次握手情况下已失效的连接请求报文段突然又传送到服务器而产生错误。考虑下面这种情况。客户A 向服务器B 发出TCP 连接请求,第一个连接请求报文在网络的某个结点长时间滞留, A 超时后认为报文丢失,于是再重传一次连接请求, B 收到后建立连接。数据传输完毕后双方断开连接。而此时,前一个滞留在网络中的连接请求到达服务器B, 而B 认为A又发来连接请求,此时若使用“三次握手”,则B 向A 返回确认报文段,由于是一个失效的请求,因此A 不予理睬,建立连接失败。若采用的是“两次握手”,则这种情况下B 认为传输连接已经建立,并一直等待A 传输数据,而A 此时并无连接请求,因此不予理睬,这样就造成了B的资源白白浪费。

question three :如果已经建立了连接,但是客户端突然出现故障了怎么办?

答:TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

question four :为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次握手。

question four :为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:1)虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum SegmentLifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。2)防止出现“已失效的连接请求报文段“(和上面的为啥不用二次握手类似)。A 在发送最后一个确认报文段后,再经过2MSL可保证本连接持续的时间内所产生的所有报文段从网络中消失.