【阅读】《Linux高性能服务器编程》——第三章:TCP协议详解:TCP协议详解

3.1 TCP服务的特点

  • TCP协议通信的双方必须先建立连接,然后进行数据的读写。双方必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输;

  • TCP连接必须是全双工的,即双方数据的读写可以通过一个连接完成。完成数据交换后,通信双方必须断开连接以释放系统资源;

  • TCP协议的连接是一对一的,不适合广播和多播;

  • 当发送端应用程序连续执行多次写操作时,TCP模块先将这些数据放入TCP发送缓冲区中。当TCP模块真正开始发送数据时,发送缓冲区中这些等待发送的数据时,发送缓冲区数据被封装成一个或多个TCP报文段发出。因此,TCP模块发出的TCP报文个数和应用程序的写操作次数之间没有固定的数量关系;

  • 当接收端接收到TCP报文后,将其按照序号依次放入TCP接收缓冲区中,并通知应用程序读取数据;

  • 发送端执行的写操作次数和接收端执行的读操作之间没有数量关系,都是字节流的概念:应用程序对数据的发送和接收没有边界限制。

  • TCP和UDP提供的服务区别:
    UDP与TCP提供服务的区别

  • TCP传输具有可靠性:TCP协议采用发送应答机制;TCP协议采用超时重传机制;TCP协议对TCP报文段会进行重排、整理,再交付给应用层。


3.2 TCP头部结构

  TCP头部结构包含固定头部结构和头部选项。

3.2.1 TCP固定头部结构

TCP头部结构

  • 16位端口号:告知主机报文段源端口和目的端口。客户端一般使用临时端口号,服务器一般使用知名服务端口号;
  • 32位序号:一次TCP通信过程中某个传输方向上字节流的每个字节的编号。
  • 4位头部长度:标识该TCP头部有多少个32bit字。
  • 6位标志位:URG标志(标识紧急指针是否有效);ACK标志(表示确认号是否有效);PSH标志(提示接收端应用程序应从TCP接收缓冲区读取数据);RST标志(要求对方重新建立连接);SYN标志(标识请求建立一个连接);FIN标志(标识通知对方本端要关闭连接);
  • 16位窗口大小:TCP控制流量的手段,告诉对方本段TCP接收缓冲区还能容纳多少字节的数据;
  • 16位校验和:发送端填充,接收端使用CRC算法进行校验查看在传输过程中是否损坏;
  • 16位紧急指针:证的偏移量,和序号字段的值相加后标识最后一个紧急数据的下一字节的序号。

3.2.2 TCP头部选项

  TCP头部的最后一个选项字段是一个可变长的可选信息,其最多包含40字节。

3.3 TCP连接的建立和关闭

3.3.1 使用tcpdump观察TCP连接的建立和关闭

$ sudo tcpdump -i eth0 -nt '(src 192.168.1.109 and dst 192.168.1.108) or (src 192.168.1.108 and dst 192.168.1.109)'
$ telnet 192.168.1.109 80

  TCP连接的建立和关闭时序图
TCP连接的建立和关闭时序图

  • 第一个TCP报文段包含SYN标志。它是一个同步报文段,即客户端向服务器发起连接请求。
  • 第二个TCP报文段也是同步报文段,表明服务器同意与客户端建立连接,帮发送自己的ISN值。同时对第一个同步报文段进行确认,即将第一个报文段的序号值加1。同步报文段没有携带任何应用程序数据,但需要占用一个序号值。
  • 第三个TCP报文段是客户端对第二个同步报文段的确认,至此TCP建立。上述为TCP三次握手。
  • 从第三个TCP报文段开始,tcpdump输出的序号值和确认值都是相对初始ISN值的偏移。
  • 第四个TCP报文段包含FIN标志,是一个结束报文段,表明客户端要求关闭连接,此报文段和同步报文段一样,需要占用一个序号值。
  • 服务器使用第五个TCP报文段确认结束报文段,并紧接着服务器发送TCP报文段6。客户端使用TCP报文段7给予确认。
  • 在连接关闭的过程中,客户端先发送结束报文段,执行主动关闭,服务器则执行被动关闭。

3.3.2 半关闭状态

  TCP连接是全双工的,允许两个方向的数据传输被独立关闭。
半关闭状态

  服务器和客户端判断对方是否关闭连接的方法是:read系统调用返回0(收到结束报文段)

3.3.3 连接超时


3.4 TCP状态转移

  TCP连接的任意一端在任意时刻都属于某一状态,当前状态可通过netstat命令查看。
TCP状态转移过程

(粗虚线表示经典服务器端连接的状态转移;粗实线表示典型的客户端连接的状态转移)

3.4.1 TCP状态转移总图

服务器状态转移过程:

  • 服务器通过listen系统调用进入LISTEN状态,被动等待客户端连接;
  • 服务器一旦监听到某个连接请求,将该连接放入内核等待队列中,并向客户端发送带SYN标志的确认报文段。此时进入SYN_RCVD状态;
  • 服务器成功接收客户端发送回的确认报文段,进入ESTABLISHED状态,此状态是连接双方都能进行双向数据传输的状态;
  • 当客户端主动关闭连接时,服务器通过返回确认报文段进入CLOSE_WAIT状态;
  • 通常,服务器检测到客户端关闭连接后,会给客户端发送一个结束报文段来关闭连接,进入LAST_ACK状态,等待客户端对结束报文段的最后一次确认,一旦确认完成,连接彻底关闭。

客户端状态转移过程:

  • 客户端通过connect主动与服务器建立连接。connect系统调用首先给服务器发送一个同步报文段,使连接进入SYN_SENT状态;
  • connect调用失败将使连接返回初始的CLOSED状态。若客户端收到服务器的同步报文段和确认,连接转移至ESTABLISHED状态;
  • 当客户端执行主动关闭时,其想服务器发送一个结束报文段,痛失进入FIN_WAIT_1状态;
  • 此时客户端收到服务器专门用于确认的确认报文段,则连接转移至FIN_WAIT_2状态,此时服务器处于CLOSE_WAIT状态;
  • 此时如果服务器也关闭连接,则客户端将基于确认并进入TIME_WAIT状态。
    TCP连接的建立和断开过程中客户端和服务器的状态变化

3.4.2 TIME_WAIT状态

  客户端连接在收到服务器的结束报文段之后,并没有进入CLOSED状态,而是转移到TIME_WAIT状态。此时,客户端连接要等待2MSL的时间,才能完全关闭。
  TIME_WAIT状态存在原因主要有:

  • 可靠地终止TCP连接
  • 保证让迟来的TCP报文段又足够的时间被识别并丢弃

3.5 复位报文段

  在特殊条件下,TCP连接的一端会向另一端发送携带RST标志的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。

3.5.1 访问不存在的端口

  当客户端程序访问一个不存在的端口时,目标主机将给它发送一个复位报文段。
  当客户端程序向服务器的某个端口发起连接,若该端口仍处于TIME_WAIT状态的连接所占用时候,客户端也将收到复位报文段。

3.5.2 异常终止连接

  TCP提供了异常终止一个连接的方法:给对方发送一个复位报文段。一旦发送复位报文段,则发送端所有排队等待的数据都将被丢弃。

3.5.3 处理半打开连接

  如果客户端或服务器向处于半打开状态的连接写入数据,此时对方则回应一个复位报文段。
  半打开状态是指:服务器或客户端关闭或异常终止了链接,而对方没有收到结束报文段,此时还维持着原来的链接。而此时服务器或客户端即使重启,也没有该链接的任何信息。


3.6 TCP交互数据流

  TCP报文段所携带的应用程序按照长度分为两种:交互数据成块数据。交互数据包含字节介绍,其对实时性要求较高;成块数据一般长度为TCP报文段允许的最大数据长度,其对传输效率较高。
  Nagle算法:要求一个TCP连接的通信双方在任意时刻都最多只能发送一个未被确认的TCP报文段,在该TCP报文段的确认到达之前,不能发送其他TCP报文段。另一方面,发送方在等待确认的同时手机本段需要发送的微量数据,并在确认来到时候以一个TCP报文段将它们全部发出,从而极大地减小网络上微小TCP报文段的数量。


3.7 TCP成块数据流


3.8 带外数据

  某些传输层协议具有带外数据的概念,用于迅速通告对方本段发生的重要事件,其相比于普通数据有更高的优先级,应该总是立即被发送。
  TCP没有真正的带外数据,其可利用头部中的紧急指针标志和紧急指针两个字段,给应用程序提供一种紧急方式。


3.9 TCP超时重传

  Linux有两个重要的内核参数与TCP超时重传相关: /proc/sys/net/ipv4/tcp_retriesl 和 /proc/sys/net/ipv4/tep_retries2。前者指定在底层IP接管之前TCP最少执行的重传次数,默认为3;后者指定放弃连接前TCP最多执行的重传次数,默认为15。


3.10 拥塞控制

3.10.1 拥塞控制概述

  • TCP拥塞控制四个部分:慢启动、拥塞避免、快速重传、快速恢复
  • 拥塞控制算法在Linux下有多种实现:reno算法、vegas算法和cubic算法。
  • 拥塞控制的最终受控变量是发送端向网络一次连续写入的数据量,即SWND(发送窗口)。发送端最终以TCP报文段来发送数据,因此SWND限制了发送端能连续发送TCP报文段的数量。TCP报文段的最大长度称为SMSS(发送者最大段大小)
    拥塞控制的输入和输出

3.10.2 慢启动和拥塞避免

  • 慢启动算法的理由:TCP模块刚开始发送数据时,并不知道网络的实际情况,需要用一种试探的方式平滑的增加CWND的大小。
  • 发送端判断拥塞发生的依据:传输超时(TCP重传定时器溢出);接收到重复的确认报文段。

3.10.3 快速重传和快速恢复

3.10.4 拥塞控制流程整理

慢开始、拥塞避免、快重传、快恢复

  • 发送放维持一个“拥塞窗口”的变量,该变量与接收窗口共同决定了发送者的发哦那个窗口。发送方的发送窗口上限值应当为接收方窗口rwnd喝拥塞窗口cwnd两个变量中较小的一个;
  • 慢 开 始 : 慢开始: 当主机开始发送数据时,为避免一下子将大量字节涌入网络中,造成或增加拥塞,发送方选择发送1字节的试探报文;
  • 当收到第一个字节的数据的确认后,就发送2个字节的报文,从此一次递增2的指数级;
  • 最后会到达一个提前预设的“慢开始门限sstresh”,此时遵循以下算法:
    若 cwnd < sstresh,停止使用慢开始算法;
    若 cwnd > sstresh,停止使用慢开始算法,改用拥塞避免算法;
    若 cwnd = sstresh,既可以使用慢开始算法,又可以使用拥塞避免算法;
  • 拥 塞 避 免 算 法 : 拥塞避免算法: 每经过一个往返时间RRT就将发送方的拥塞窗口+1,让拥塞窗口缓慢增大,按照线性规律增长;
  • 当出现网络拥塞,将慢开始门限ssthresh设置为出现拥塞时的发送窗口的一半(但不能小于2),然后将cwnd设为1,开始执行慢开始算法;
  • 快 重 传 机 制 : 快重传机制:
    1、接收方建立机制:如果一个包丢失,则对后续的包继续发送针对该包的重传请求;
    2、一旦发送方接收三个一样的确认,就知道该报出现了错误,立即重传该包;
    3、此时执行 快 恢 复 算 法 : 快恢复算法:
      a、慢开始的门限变为出现拥塞时的一半;
      b、拥塞窗口cwnd设为上面变化后的慢开始的门限值;
      c、执行拥塞避免算法(高起点,线性增长);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甄姬、巴豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值