TCP——(1)

1.TCP协议分析流程


  [1]要分析整个TCP协议,需要从外向里去分析,首先就是分析af_inet.c,这个里面就是inet的接口函数,例如bind()、listen()等等,之后就是弄清楚这些函数(函数的参数)是要干什么。

  [2]之后继续分析TCP的握手流程。

  [3]之后继续分析TCP的数据传输流程。

  [4]之后继续分析TCP的断链流程。

  [5]之后继续分析TCP的拥塞控制流程。

  [6]之后继续分析TCP的其他分支流程。

2.TCP连接建立(三次握手)


  TCP的根本目的是可靠地传输数据,如果不需要可靠地传输,则不需要握手,直接发数据就可以(例如UDP)。

  而为了保证可靠地传输数据,便需要两端维护一些信息(序号、ACK号等等)。握手就是同步这些信息的过程,只有保证信息同步完成了,才能开始交互数据。

    [1]A向B发送SYN,A向B同步本端的连接信息(seq、MSS、SACK选项等等)。

    [2]B向A发送SYN ACK,SYN表示B向A同步本端的连接信息(seq、MSS、SACK选项等等),ACK表示对A的SYN的确认。

    [3]A收到SYN ACK后进入establish状态;然后A向B发送ACK(对B的SYN的确认),B收到这个ACK后也进入establish状态。

  握手是双方的事情,即双方都进入establish状态时,表示握手完成。

3.TCP连接释放


  连接释放的目的是关闭本端的连接(进入CLOSE状态),因为最后对B来说四次挥手全部完成,所以B收到最后的ACK后便可以直接关闭连接,而由于A发送ACK之后不会再收到后续报文,并且A无法保证最后的ACK被B收到,所以A要等待2MSL之后再关闭连接(进入CLOSE状态)。另外就是谁主动关闭连接谁进入CLOSE_WAIT,并不区分客户端还是服务器。

  被动关闭处理:

    收到fin报文之后,回复ack,当本端数据发送完后,发送fin,之后收到对方ack,此时本端进入close状态。

  主动关闭处理:

    发送fin报文,收到对端ack,当收到对端fin之后,回复ack,之后等待2MSL时间后进入close状态。

    等待2MSL的原因:

      [1]防止最后的ack丢包。如果丢了,因为本端还在等待,所以可以正常处理对端的fin重传,要是不等就无法处理了。

        理论被动方在收到ack之后再发送一个特殊报文再进入close,这样就可以解决这个问题,但是还有下面的原因,所以没有必要这样做。

      [2]防止最后的报文影响新的链接。比如新的链接还是相同的四元组,这样最后还在链路传输的报文就会影响新的链接。                 

4.TCP有限状态机


  下图的线并不代表某端,而是表示流程(例如客户端可以主动打开(客户端发送SYN)但是被动关闭(服务器首先发送FIN)),粗实线表示主动流程,虚实线表示被动流程,普通实线表示其他流程,例如上面两行说明的。

 

5.TCP定时器


  【1】保活定时器

    保活功能主要在服务器设置,如果一个连接在2个小时之内没有任何动作(没有任何数据传输),则服务器就向客户发送一个探查报文段。在TCP连接建立的时候指定了SO_KEEPALIVE,保活定时器才会生效。

    和http keepalive的区别:

      tcp keepalive用于回收空闲的tcp连接,以释放服务器的资源,提升服务器的性能。

      http keepalive用于复用同一个tcp连接以承载多个http请求,这样减少了连接建立的三次握手和关闭的四次握手,这样降低了网络开销,也减轻了服务器压力。

  【2】延迟应答定时器

    延迟应答也被成为捎带ACK, 这个定时器是在延迟应答的时候使用的。 延迟应答是为了提高网络传输的效率。

    如果在等待发送ACK期间,第二个数据又到了,这时候就要立即发送ACK。

    举例说明,比如服务端收到客户端的数据后, 不是立刻回ACK给客户端, 而是等一段时间(一般最大200ms),这样如果服务端要是有数据需要发给客户端,那么这个ACK就和服务端的数据一起发给客户端了, 这样比立即回给客户端一个ACK节省了一个数据包。

    优点:减少了数据段的个数,提高了发送效率。

    缺点:过多的delay ack会拉长RTT。

   【3】坚持定时器(persist timer)

    如果接收窗口变为0之后,则对端将停止发送数据,等接收窗口变为非0时,会向发送端发送一个ACK报文,这个报文本身自带窗口大小,用来通知对端继续发送。但是如果这个ACK丢失了,则双方可能因为都在等待对方而连接终止:

接收方等待接收数据(因为它已经向发送方通告了一个非0的窗口),而发送方在等待允许它继续发送数据的窗口更新。

    为防止这种死锁情况的发生,发送方使用一个坚持定时器 (persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查报文 (window probe)。

  【4】重传定时器(retransmission timer)

    重传定时器在TCP发送数据时设定,在计时器超时后没有收到返回的确认ACK,发送端就会重新发送队列中需要重传的报文段。

  【5】TIME_WAIT定时器 (TIME_WAIT timer, 也叫2MSL timer)

    TIME_WAIT是主动关闭的一端最后进入的状态,此时不能直接变成CLOSED的状态,这么做的原因:

      [1]如果被动关闭的一端在超时时间内没有收到最后一个ACK, 则会重发最后的FIN,2MSL(报文段最大生存时间)等待时间保证了重发的FIN会被主动关闭的一段收到且重新发送最后一个ACK;

      [2]在2MSL等待时间时,任何迟到的报文段会被接收并丢弃,防止老的TCP连接的包在新的TCP连接里面出现。

  【6】建立连接定时器(connection-establishment timer)

    这个定时器是在建立连接的时候使用的,TCP在建立连接发送SYN时,会启动一个定时器(默认应该是3秒),如果SYN包丢失了,那么3秒以后会重新发送SYN包的(此时还会启动一个新的定时器,设置成6秒超时)。  

    在/proc/sys/net/ipv4/tcp_syn_retries可以设置一共重新发送几次SYN包。

 

 

 

 

 

 

 

 

 

  

    

posted on 2019-03-04 11:24  能量星星  阅读(486)  评论(0编辑  收藏  举报

导航