TCP

TCP(Transmission Control Protocol,传输控制协议),是一个传输层协议。TCP 提供客户与服务器之间的连接。TCP 客户先与某个给定的服务器建立一个连接,再通过该连接与服务器交换数据,最后再终止该连接。


特性

1.可靠性
TCP 在向对端传输数据时,要求对方收到数据后返回一个确认。如果在等待一定时间后没有收到确认,则自动重传该数据并等待更长的时间。只有在数次重传都失败后,TCP 才会放弃这次传输同时告知用户。

TCP 的可靠性并不意味着数据一定会被对端接受

2.RTT估算
RTT(Round-trip time),TCP 会动态估算客户和服务器之间的往返时间,以便它了解在特定的网络状况下等待一个确认需要花费多久的时间。

3.***
TCP 通过对不同 TCP 分节的数据字节进行编号,来确认数据的先后顺序和漏发、重发的情况。

4.流量控制
TCP 总是告知对端在任何时刻它一次能够从对端接受的数据,这称为通告窗口。通告窗口的大小会随着发送端数据接受和接收端应用读取数据的发生而变化。

5.全双工
建立 TCP 连接后,能够同时在该连接上发送、接受数据。

全双工不意味着连接是反向相等的,两端数据的传输可能经过不同的路由

6.面向流
TCP 传输数据不会保留 TCP 数据报的边界信息


TCP 首部

TCP 简单介绍

  1. 同UDP 首部一样,TCP 首部有2字节的源端口目的端口
  2. 序号位总共有4个字节,序号的范围为 [0, 2 ^ 32 - 1]。TCP对数据段的所有字节都会进行编号,在序号位填写的是数据段中的第一个字节的序号。
  3. 确认号位也有4个字节,确认号的范围同样为[0, 2 ^ 32 - 1]。确认号位填写的是期望对方下一个TCP 报文首部中序号位的数值。举个简单例子,B端从A端收到了序号为100,数据段长度为200的 TCP 报文(数据段的序号从100到299)。那么B端发送给A端的 TCP 报文的确认号应该是300,表示希望下次从A端收到的 TCP 报文首部的序号是300。
  4. HLEN 位有4个比特,数值范围为[0, 15]。HLEN 位实际表示 TCP 首部的长度,首部长度 = HLEN 值 × 4。
  5. 保留位目前没什么用处,均置为0。
  6. ACK,确认位。在 TCP 连接建立完成后,所有的 TCP 报文均要将 ACK 置为1。
  7. SYN,同步位。在建立 TCP 连接时,同步序号。当收到 TCP 报文且 SYN = 1,而ACK = 0时,表明对方想和我们建立 TCP 连接。
  8. FIN,终止位。在终止 TCP 连接时,将 FIN 置为 1。
  9. 窗口大小位有2个字节(通告窗口),数值范围为[0, 65535]。这个值表明了发送方接收窗口的大小,即从这次的确认号开始,还能接受的数据的大小。
  10. 校验和,将伪首部、首部和数据段放在一起计算校验和,计算校验和时将校验和位置0。
  11. 选项与填充
    MSS选项,发送 SYN 的 TCP 一端使用本选项告知对端它的最大分节大小(maximum segment size)。
    窗口规模选项,TCP 连接任何一端能够通告对端的最大窗口大小时65535,因为在 TCP 首部中相应的字段占16位。这个新选项指定 TCP 首部中的通告窗口必须扩大的位置(0~14)。
    时间戳选项

TCP 三次握手和四次挥手

三次握手

建立一个 TCP 连接时会发生如下的情形:
1.服务器必须准备好接受外来的连接。在代码上通过调用 socket、bind 和 listen 这三个函数完成。我们称之为被动打开(passive open)。
2.客户端通过调用 connect 发起主动打开(active open)。客户端 TCP 发送一个 SYN 分节,它告诉服务器客户将在(待建立的)连接中发送的数据的初始***。通常 SYN 分节不携带数据,其所在 IP 数据报只含有一个 IP 首部、一个 TCP 首部及可能有的 TCP选项。
3.服务器必须确认(ACK)客户的 SYN,同时自己也得发送一个 SYN 分节,它含有服务器将在同一连接中发送的数据的初始***。服务器在单个分节中发送 SYN 和对客户 SYN的 ACK。
4.客户必须确认服务器的 SYN。

这种交换至少需要3个分组,因此称之为TCP的三次握手(three-way handshake)。

TCP 简单介绍
PS:按照上文所说,如果 SYN 分节不带任何数据,为什么服务器和客户端的序号和确认号会一直在变呢?
事实上,SYN 和 FIN 若置为1,都会占据长度为1的序号。因此客户端的 SYN 分节中的序号为J时,服务器发送的 SYN ACK 分节的确认序号会是J + 1。
之所以 SYN 和 FIN 这么特殊,是因为 SYN 和 FIN 是唯二需要确认的控制位。

四次挥手

终止一个 TCP 连接会发生如下情形:
1.某个应用进程首先调用 close,我们称该端主动关闭(active close)。该端的 TCP 于是发送一个 FIN 分节,表示数据发送完毕。
2.接收到这个 FIN 分节的对端执行被动关闭(passive close)。这个 FIN 由 TCP 确认。它的接受也作为一个文件结束符(end-of-file)传递给接收端应用程序。
3.一段时间后,接受到这个文件结束符的应用进程将调用 close 关闭它的套接字。这导致它的 TCP 也发送一个 FIN。
4. 接受这个最终 FIN 的原发送端 TCP 确认这个 FIN。

TCP 简单介绍
MSL,maximum segment lifetime 最长分节生命。


TCP 状态转换

TCP 简单介绍
TIME_WAIT 状态必须存在的两个理由:
1.可靠地实现 TCP 全双工连接地终止
2.允许老的重复分节在网络中消逝


TCP 输出

每一个 TCP 套接字由一个发送缓冲区,我们可以使用 SO_SNDBUF 套接字选项来更改缓冲区大小。当某个应用程序调用 write 时,内核从该应用程序的缓冲区中赋值所有数据到套接字的发送缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将会休眠(默认 write 为阻塞的),直到应用进程缓冲区中的所有数据都被赋值。因此,从写一个 TCP 套接字的 write 调用返回成功仅仅表示我们可以使用原来的应用进程缓冲区。

TCP 简单介绍

由于 TCP 的可靠性,在收到对端的确认之前,数据需要保存在发送缓冲区中。伴随来自对端的 ACK 的不断到达,本段 TCP 才能从套接字发送缓冲区中丢弃已确认的数据。 TCP 必须为已发送数据保留一个副本,直到它被对端确认为止。

本端 TCP 以 MSS 大小或更小的块把数据传递给 IP,同时给每个数据块按上一个 TCP 首部已构成 TCP 分节,其中 MSS 或是对端通告的值,或是536(若对端未发送一个 MSS 选项,536是 IPv4 最小重组缓冲区字节数576减去 IPv4固定首部字节数20和 TCP 固定首部字节数20的结果)。
MSS 选项的目的之一就是避免被 IP 层分片。

相关文章: