TCP协议详解

66 阅读8分钟

序言

    TCP协议是TCP/IP协议族中另一个重要的协议。和IP协议相比,TCP协议更靠近应用层,因此在应用程序中具有更强的可操作性。一些重要的socket选项都和TCP协议相关。TCP协议可以从4方面来讨论:

  • TCP头部信息(源端口,目的端口,管理TCP连接,控制两个方向的数据流)
  • TCP状态转移过程(客户端和服务端都是一个状态机)
  • TCP数据流(交互数据流和成块数据流)
  • TCP数据流控制(超时重传和拥塞控制)

TCP服务的特点

传输层协议主要有2个:TCP和UDP。TCP相比UDP的特点是

  • 面向连接
  • 面向字节流
  • 可靠传输

面向连接:使用TCP协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。完成数据交换之后,通信双方都必须断开连接以释放系统资源。 TCP协议的这种连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服务。而无连接协议UDP则非常适合于广播和多播。
面向字节流:字节流服务和数据报服务的区别对应到实际编程中,则体现为通信双方是否必须执行相同次数的读、写操作(当然,这只是表现形式)。当发送端应用程序连续执行多次写操作时,TCP模块先将这些数据放入TCP发送缓冲区中。当TCP模块真正开始发送数据时,发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出。因此,TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系。 当接收端收到一个或多个TCP报文段后,TCP模块将它们携带的应用程序数据按照TCP报文段的序号(见后文)依次放入TCP接收缓冲区中,并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读出,也可以分多次读取,这取决于用户指定的应用程序读缓冲区的大小。因此,应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间也没有固定的数量关系。

TCP字节流服务 image.png UDP数据报服务 image.png

可靠传输:首先,TCP协议采用发送应答机制,即发送端发送的每个TCP报文段都必须得到接收方的应答,才认为这个TCP报文段传输成功。其次,TCP协议采用超时重传机制,发送端在发送出一个TCP报文段之后启动定时器,如果在定时时间内未收到应答,它将重发该报文段。最后,因为TCP报文段最终是以IP数据报发送的,而IP数据报到达接收端可能乱序、重复,所以TCP协议还会对接收到的TCP报文段重排、整理,再交付给应用层。 UDP协议则和IP协议一样,提供不可靠服务。它们都需要上层协议来处理数据确认和超时重传。

TCP头部信息

image.png

  • 16位端口号(port number):告知主机该报文段是来自哪里(源端口)以及传给哪个上层协议或应用程序(目的端口)的。进行TCP通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号。1.3节中提到过,所有知名服务使用的端口号都定义在/etc/services文件中。
  • 32位序号(sequence number):一次TCP通信(从TCP连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号。假设主机A和主机B进行TCP通信,A发送给B的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(Initial Sequence Number,初始序号值)。那么在该传输方向上(从A到B),后续的TCP报文段中序号值将被系统设置成ISN加上该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个TCP报文段传送的数据是字节流中的第1025~2048字节,那么该报文段的序号值就是ISN+1025。另外一个传输方向(从B到A)的TCP报文段的序号值也具有相同的含义。
  • 32位确认号(acknowledgement number):用作对另一方发送来的TCP报文段的响应。其值是收到的TCP报文段的序号值加1。假设主机A和主机B进行TCP通信,那么A发送出的TCP报文段不仅携带自己的序号,而且包含对B发送来的TCP报文段的确认号。反之,B发送出的TCP报文段也同时携带自己的序号和对A发送来的报文段的确认号。
  • 4位头部长度(header length):标识该TCP头部有多少个32bit字(4字节)。因为4位最大能表示15,所以TCP头部最长是60字节。
  • 6位标志位包含如下几项:
    • ❑URG标志,表示紧急指针(urgent pointer)是否有效。
    • ❑ACK标志,表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。
    • ❑PSH标志,提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在TCP接收缓冲区中)。
    • ❑RST标志,表示要求对方重新建立连接。我们称携带RST标志的TCP报文段为复位报文段。
    • ❑SYN标志,表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段。
    • ❑FIN标志,表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段为结束报文段。
  • 16位窗口大小(window size):是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
  • 16位校验和(TCP checksum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。
  • 16位紧急指针(urgent pointer):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法。
    这里最常用的其实是端口号(目标+源)序号确认号
    端口号并不复杂,序号和确认号我们可以看个例子巩固下理解:

image.png

seq都是发起方新发起的序号,ack是接收方在发起方的seq基础上+1;在关闭连接时,双方需要拿着上次连接建立成功的ack,准确关闭

TCP状态转移过程

    掌握下面两张图足以:

image.png image.png

TIME_WAIT状态:在这个状态,客户端连接要等待一段长为2MSL(Maximum Segment Life,报文段最大生存时间)的时间,才能完全关闭。MSL是TCP报文段在网络中的最大生存时间,标准文档RFC 1122的建议值是2 min。 TIME_WAIT状态存在的原因有两点:

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

TCP数据流

    TCP报文段所携带的应用程序数据按照长度分为两种:交互数据成块数据。交互数据仅包含很少的字节。使用交互数据的应用程序(或协议)对实时性要求高,比如telnet、ssh等。成块数据的长度则通常为TCP报文段允许的最大数据长度。使用成块数据的应用程序(或协议)对传输效率要求高,比如ftp