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   能量星星  阅读(504)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示