目录
1.连接的建立与断开
TCP 协议提供的是:面向连接、可靠的、字节流服务。
使用 TCP 协议通信的双发必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP 连接是全双工的,双方的数据可以通过一个连接进行读写。完成数据交换之后,通信双方都必须断开连接以释放系统资源。
- 三次握手发生在客户端执行 connect()的时候,该方法返回成功,则说明三次握手已经建立。
- 四次挥手发生在客户端或服务端执行 close()关闭连接的时候:
2.TCP状态转移
TCP 连接的任意一端在任一时刻都处于某种状态,当前状态可以通过 netstat 命令查看,下图是 TCP 连接从建立到关闭整个过程中通信两端状态的变化。其中 CLOSED 是假想的起始点,并不是一个实际的状态。
TIME_WAIT 状态一般情况下是主动关闭的一端才会出现的状态。该状态出现后,会维持一段长为 2MSL(Maximum Segment Life)的时间,才能完全关闭。MSL 是 TCP 报文段在网络中的最大生存时间,标准文档 RFC1122 的建议值是 2min。
TIME_WAIT 状态存在的原因有两点:
- 可靠的终止TCP连接
- 保证让迟来的TCP报文有足够的时间被识别并被丢弃
3.复位报文段
在某些特殊条件下,TCP 连接的一端会向另一端发送携带 RST 标志的报文段,即复位报文段,已通知对方关闭连接或重新建立连接。
3.1 访问不存在的端口
当客户端程序访问一个不存在的端口时,目标主机给它发送一个复位报文段。
当客户端程序向服务器的某个端口发起连接,而该端口仍被处于TIME_WAIT状态的连接所占用时,客户端程序也将收到复位报文段。
3.2 异常终止连接
正常终止方式为:数据交换完成之后,一方给另一方发送结束报文段。
TCP提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。
应用程序可以通过使用socket选项SO_LINGER来发送复位报文段,以异常终止一个连接。
3.3 处理半打开连接
检测半打开连接:
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的 TCP连接称为半打开(H a l f - O p e n)的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。
/*
例如 TCP 一端关闭了连接,由于网络故障对方没有收到结束报文,对方误以为连接仍然正常。处于这种状态的连接称为半打开连接。 */
此时如果对端向连接写入数据,则会收到本端回复的复位报文段。
4. 交互数据流和成块数据流
TCP 按照携带应用程序数据长度可以分为两种:交互数据和成块数据。交互数据仅包含很少的字节。使用交互数据的应用程序对实时性要求极高,比如 telnet、ssh 等。成块数据的长度则通过为 TCP 报文段允许的最大数据长度。使用成块数据的应用程序对传输效率要求高,比如 FTP。
5. 带外数据
有些传输层协议具有带外(out of Band,OOB)数据的概念,用于迅速通告对方本端发生的重要事件。因此,带外数据比普通数据有更高的优先级,它应该总是立即被发送,而不论发送缓冲区中是否有排队等待发送的普通数据。
先来介绍TCP发送带外数据的过程。假设一个进程已经往某个TCP连接的发送缓冲区中写人了N字节的普通数据,并等待其发送。在数据被发送前,该进程又向这个连接写人了3字节的带外数据“abc”。此时,待发送的TCP报文段的头部将被设置URG标志,并且紧急指针被设置为指向最后一个带外数据的下一字节(进一步减去当前TCP报文段的序号值得到其头部中的紧急偏移值)。
UDP 没有实现带外数据传输,TCP 也没有真正的带外数据。不过 TCP 利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供了一种传输紧急数据的方式。一般只有一个字节数据。
6.流式服务特点
TCP 字节流的特点,发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的。
7.应答确认与超时重传
TCP 发送的报文段是交给 IP 层传送的。但 IP 层只能提供尽最大努力的服务,也就是说,TCP 下面的网络所提供的是不可靠的传输。因此,TCP 必须采用适当的措施才能使两个运输层之间的通信变得可靠。TCP 的可靠传输是通过使用应答确认和超时重传来完成。
通过 netstat 命令抓包看到的信息:
无差错时候,数据交互的流程:
发送端发送数据 m1 给接收端,接收端收到数据后会给发送端一个确认信息,以表明数据已经被成功收到。在发送方未收到确认信息前,M1应继续被保留,直到确认信息到达才能丢弃。
出现差错时,交互流程:
8. 滑动窗口
TCP 协议是利用滑动窗口实现流量控制的。一般来说,我们总是希望数据传输得更快一些,不会一次只发一个字节。但是如果发送方把数据发得过快,接受方就可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。
在 TCP 的报头中有一个字段叫做接收通告窗口,这个字段由接收端填充,是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以发送端就会有一个发送窗口,这个发送窗口的大小是由接收端填充的接收通告窗口的大小决定的,并且窗口的位置会随着发送端数据的发送和接收到接收端对数据的确认而不断的向右滑动,将之称为滑动窗口。
图示:
当收到 36 的 ack,并发出 46-51 的字节后,窗口滑动的示意图如下:
9. 拥塞控制
TCP模块还有一个重要任务,就是提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性,这就是所谓的拥塞控制。
拥塞控制是一个全局性的过程,涉及到所有主机,
所有路由器,以及与降低网络传输性能有关的所有因素。
几种拥塞控制的方法:
- 慢启动
- 拥塞避免
- 快速重传
- 快速恢复
慢开始、拥塞避免、快速恢复示意图:
快速重传图示: