如何理解传输层协议(TCP、UDP)

 

前言

前面我们介绍过,网络底层的通信是通过一个个小的数据包进行的。当需要传输大量数据时,数据通常会被分割成多个小包,每个小包通过网络传输。这种数据包的传输方式虽然高效,但也带来了一些挑战。网络环境本身是不稳定的,数据包的到达顺序不可预期,甚至数据包可能在传输过程中丢失或者失真,导致传输的数据出错或不完整。

为了应对这些问题,传输层协议应运而生。传输层的主要任务是在不可靠的网络环境中确保数据能够正确地从一个点传输到另一个点。TCP和UDP是传输层协议的代表,它们各自解决了不同的网络传输问题。

TCP协议

TCP的来历与发展

TCP(Transmission Control Protocol, 传输控制协议)最初由 Vint CerfBob Kahn 于1974年提出,作为Internet协议族的一部分。TCP的设计目的是提供一种可靠的、面向连接的数据传输服务,尤其适用于需要高可靠性的应用,如电子邮件和文件传输。

TCP的初步定义在RFC 675: Specification of Internet TCP中,随着互联网的发展,TCP的规范不断被改进和完善,直到成为今天我们所熟知的协议。

其他相关文档包括:

TCP的特性

TCP协议的核心特性包括:

  1. 面向连接:在数据传输之前,必须先通过三次握手建立连接,保证双方都准备好进行数据交换。
  2. 可靠传输:通过序列号、确认号、校验和等机制,确保数据包的顺序、完整性和无误。
  3. 流量控制:通过滑动窗口机制控制数据的传输速率,防止接收端溢出。
  4. 拥塞控制:在网络拥塞时,动态调整数据的发送速率,避免网络的过载。

什么是连接?

连接的定义在RFC文档中有过明确说明:

RFC675

   A pair of sockets form a CONNECTION which can be used to carry data
   in either direction [i.e. full duplex]. The connection is uniquely
   identified by the <local socket, foreign socket> address pair, and
   the same local socket can participate in multiple connections to
   different foreign sockets

RFC793

Connections:

    The reliability and flow control mechanisms described above require
    that TCPs initialize and maintain certain status information for
    each data stream.  The combination of this information, including
    sockets, sequence numbers, and window sizes, is called a connection.
    Each connection is uniquely specified by a pair of sockets
    identifying its two sides.

在TCP协议中,连接是由一对套接字(Socket)确立的。套接字是操作系统提供的网络接口,它允许程序在网络中进行数据的收发。本质是为一对通信的进程(客户端和服务端)提供一个稳定的通道,所有通过TCP协议传输的数据都需要通过这个连接。每个连接由五元组唯一标识:

  • 本地IP地址
  • 本地端口号
  • 远程IP地址
  • 远程端口号
  • 协议类型(TCP)

通过这五个元素的组合,操作系统能够唯一识别每个连接,确保数据能够正确发送和接收。

三次握手

为什么要有三次握手?

三次握手的目的是为了初始化连接的传输参数设置,确保双方都准备好进行数据传输:

  1. 通过交换序列号来确认双方都准备好接收数据。
  2. 交换必要的连接参数,如窗口大小、序列号等,以保证连接的正常建立。

三次握手的过程由以下几个步骤组成:

  1. 客户端发送SYN请求:客户端首先发送一个SYN包,表示请求连接,并选择一个初始序列号。
  2. 服务端回应SYN-ACK:服务端收到SYN包后,回应一个SYN-ACK包,表示同意连接,并告知其初始序列号。这实际上是两个数据,只是合并在一个数据包里发送出去。
  3. 客户端确认ACK:客户端收到SYN-ACK包后,发送一个ACK包,确认连接建立。
图1: TCP三次握手过程

为什么需要三次而不是两次?

首先,三次握手和两次的区别就是,对SYNC需不需要进行ACK

答案是需要:

  • 避免重复连接请求:客户端和服务端可以通过序列号确认连接请求的唯一性。

    如果SYNC数据包传输延迟较高,客户端进行了重试,那服务端可能会收到2个重复的建立TCP请求(其中一个是已经过期的),通过ACK的机制,客户端可以通过比对Seq明白哪个ACK是当前连接的。

  • 双方同步连接信息:三次握手确保了客户端和服务端都确认了彼此的接收能力和状态。

四次挥手

为什么要有四次挥手?

四次挥手的目的是为了可靠地断开TCP连接,确保双方都能够完成数据的传输,且连接能够彻底关闭。四次挥手的过程如下:

  1. 主动关闭方发送FIN包:当客户端或者服务端完成数据传输后,主动关闭方发送一个FIN包,表示自己不再发送数据。
  2. 接收方确认FIN:接收方收到FIN包后,发送ACK包确认收到FIN包,并进入关闭等待状态。
  3. 接收方发送FIN包:接收方也完成数据传输后,向主动关闭方发送一个FIN包,表示自己也不再发送数据。
  4. 主动关闭方确认FIN:主动关闭方收到接收方的FIN包后,发送ACK包确认,连接正式关闭。

四次挥手确保了双方都可以在合适的时机断开连接,且数据不会丢失或被误处理。

为什么需要四次而不是三次?

因为被关闭方的ACK和FIN不能合在一起发送

  1. 当收到FIN后,需要立即回复一个ACK。
  2. 此后将缓冲区未发送的数据发送完毕后,再发送一个FIN包,表示剩余数据传输完毕。
图2: TCP四次握手过程

UDP协议

UDP的发展过程

UDP(用户数据报协议)是TCP协议的对立面,最早由 David P. Reed 于1980年提出,并在 RFC 768 中进行定义。与TCP不同,UDP是一个无连接的协议,不提供可靠性保障。它的设计目标是低延迟和简单性,适合对速度要求高、对丢包不敏感的应用场景。

相关文档:RFC 768: User Datagram Protocol

有了TCP为什么还需要UDP?

尽管TCP提供了可靠的传输,但它也带来了较大的开销,尤其是在需要快速响应和低延迟的场景中,TCP可能显得过于笨重。UDP没有像TCP那样的连接建立过程、数据确认、流量控制等机制,提供了更为简洁的传输方式。

UDP允许应用层自行处理丢包、顺序、流量控制等问题,因此它更适合需要低延迟且对数据丢失容忍的应用。例如:

  • 实时视频和音频通信(如视频会议)
  • 在线游戏(如多人在线对战游戏)
  • DNS查询

TCP协议在操作系统内核中得到了统一实现,而UDP则更为灵活,允许用户根据自己的需求实现具体的协议细节。这样,UDP能够提供更大的自由度和效率,但也需要开发者更多的工作来确保协议的可靠性和顺序性。

ISP对TCP、UDP的处理

数据包的特征与识别

TCP和UDP数据包在协议头部有明确的标识,运营商可以通过这些特征进行识别。例如,TCP数据包包含了源端口、目的端口、序列号等信息,而UDP则通过源端口和目的端口来标识数据包的来源和目标。

ISP(Internet Service Provider, 网络供应商)对UDP的处理

在网络负载较高时,一些ISP会选择性地丢弃UDP数据包,特别是当这些数据包的传输带宽占用较高时。因为UDP没有像TCP那样的流量控制机制,它的传输更容易受到网络拥塞的影响,因此ISP有时会采取策略来丢弃UDP数据包,以保证网络稳定性。

当前TCP和UDP的应用

TCP的应用

由于TCP的可靠性,它已经成为互联网应用的事实标准。大多数需要保证数据可靠传输的应用程序,如HTTP(Web浏览)、FTP(文件传输)、SMTP(电子邮件)等,都使用了TCP。由于TCP实现复杂且在操作系统内核中统一管理,普通用户和应用程序通常无需关心其细节。

UDP的应用

与TCP不同,UDP的灵活性使其能够在特定场景下提供优异的性能,特别是在实时应用中。UDP常常和应用层协议结合使用,例如:

  • QUIC协议:由Google提出,结合了TCP和UDP的优点,用于提升HTTP/2协议的性能,减少延迟。
  • 实时流媒体:如视频会议、VoIP等实时传输协议,通常使用UDP以减少延迟。

总结

本文介绍了TCP和UDP协议的基本原理、发展过程及其应用场景。

  1. 我们讲解了TCP的本质是由一对相互通讯的Socket组成的连接,也讲解了建立、断开连接的交互流程和设计本质。
  2. 我们讲解了UDP协议是对TCP的重要补充,基于UDP协议实现的应用层协议在很多场景下解决了TCP的性能问题。