TCP协议详解_动力节点Java学院整理
TCP中除了通常的数据交换报文(数据报文详见后文“数据传输”小节),还有以下一些特殊的控制报文:SYN报文、ACK报文、FIN报文、RST报文、窗口探测报文、持活报文。这里将常见报文列出来,一是为了强调一个事实,TCP的状态变更大部分是通过报文交互进行的;二是对各种控制报文的使用场景进行简单归纳。 SYN报文,用于发起一个新连接,只包含TCP首部,没有数据。一个典型报文输出如下: 10:23:17.543837 IP 192.168.47.1.55366 > krt.9876: Flags [S], seq 2289863414, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0 ACK报文,用于对控制报文(不包括RST)和数据报文进行确认,参考上一小节关于ACK的一些注意点。该报文可以与其他报文结合在一起,如SYN、数据报文、FIN报文等。单独的ACK本身不含任何数据,只有首部,典型报文输出如下: 10:23:17.544135 IP 192.168.47.1.55366 > krt.9876: Flags [.], ack 1, win 16425, length 0 FIN报文,用于通知对端已经发送完了所有数据,将发送缓冲区中数据发送完成后,可以关闭连接。详细参考后文“连接控制”,用于有序释放连接或者连接半打开。 RST报文,当向一个出现错误的连接发送一个报文的时候,就收到RST报文。以下是几种典型情况(详细情景在后文“连接控制”小节表述): 对端的相应端口上没有监听程序 异常终止连接,SO_LINGER。使用异常方式终止连接,而不是正常的有序终止连接orderly release,可以迫使连接直接丢失未发送的数据;而接收方收到RST报文后,read返回reset错误,从而终止该连接,同时不会进行ACK。 检测半打开连接,一方已经关闭或异常终止连接而另一方还不知道。造成这种状况的原因在于通信的一方没有正确将相应的状态报文成功发送给对端,如主机突然掉电导致FIN报文没有发出去,此时再写该socket,则会得到RST报文。 窗口探测报文(持久探测报文),TCP并不会对不包含数据的ACK报文进行确认,因此可能出现ACK丢失,从而导致窗口通告失败。TCP使用persist定时器,定期的发送一个字节的窗口探测报文。探测报文总是在5~60s之间,也是采用指数后退算法,但不超过60s,该探测报文会一直持续。实现时,使用500ms的定时器。 持活报文,用于查看连接是否仍然存活的控制报文。报文只带有ACK标志,且序号字段为将要发送的序号减一,这样引起对端进行一个ACK,表示接收到重复序号,对端期望的序号为下一个值。 连接控制 TCP是面向连接的协议,正如前面所描述的,并不存在真实的物理或虚拟的链路,TCP的连接是指在通信的双方分配了资源和维护了状态,并通过控制报文控制连接,通过API协调资源。本小节将详细描述实现中对TCP的连接控制。需要注意的是,连接的拥塞控制在本小节不过多涉及,后面单独小节描述。 4个定时器:重传定时器、2MSL定时器、persist定时器、keepalive定时器 连接双方通过以下一些事件来维持连接的状态, 发送方:发送缓冲区、4个定时器、发送窗口、拥塞状态计数器 接收方:接收缓冲区、4个定时器、接收窗口、拥塞状态计数器 TCP连接更详细的描述 通信双方通过一些内部状态保持了彼此的信息,连接关系始终保持,并通过报文交换来进行连接状态的变更。由于是通过报文进行连接状态的维护,所以报文没有正确发出或被接收到时,连接状态就会变成意料之外了;除确认报文本身不被确认,其他报文都会有确认报文进行确认;报文(包括确认报文)可能超时、需要重传。下面是通信过程中一些重要报文的交互序列。 发送方 网络(中间路由器等组成) 接收方 发送方为Windows,接收方为Linux,操作如下 krt@krt:~$ perl ksock.pl --sleep-before-listen=1 连接建立 连接建立过程中会经历被称为“三次握手”的报文交互。 连接建立过程主要目的在于协商双方通信的细节,双方的初始序列号、窗口大小、最大报文段MSS大小等。 连接断开 数据传输 数据交换(基本的确认、超时、重传,滑动窗口) 交互数据和批量数据交换 拥塞控制 性能和常用网络工具 tcpdump lsof netstat ss /proc (编辑:焦作站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |