在讲解TCP与UDP之前,首先看一下它们在网络协议栈上的位置:
所谓网络协议栈,就是对网络进行分层次的梳理,主要有OSI七层模型和ICP/IP的四层模型,对应关系如下图所示,主要介绍TCP/IP的四层模型:
TCP/IP模型分为四层,分别是链路层、网络层、传输层、应用层,应用层以下的三层都是在操作系统的内核中进行。
- 链路层:包括操作系统中的驱动程序和计算机网卡还有传输的物理介质,链路层上面的主要协议有以太网协议;
- 网络层:保证数据从一台主机将数据准确的发送到另一台指定的主机,主要通过指定IP地址(点分十进制)和端口号(表明应用程序)来实现,主要的协议有IP协议,ARP、RARP、ICMP和IGMP作为辅助协议。路由器属于网络层;
- 传输层:网络层提供了一种不可靠的服务,它只是尽可能快把分组从源端口发送到目的窗口,但是并不能保证能毫发无损地准时送到。而传输层则利用TCP,UDP协议来保证传输。TCP采用超时重传,发送和接收端分组等机制来实现可靠传输。主要协议有TCP,UDP,TCP数据和UDP数据基本一致,唯一的区别是UDP传给IP的协议的信息单元称为UDP数据报;
- 应用层:负责应用程序的具体需求,主要协议有FTP,TELNET,HTTP,HTML,STMP,POP,IMAP,DNS等。
可见:TCP、UDP就是处于其中的传输层。各层之间的协议如下图所示:
传输层
既然有了IP协议(网络层),能将数据发送到指定的主机为什么还要由传输层。原因有两点:
- IP协议提供的是不可靠的传输协议,它只是尽力将数据发送到目标主机,但是如果数据丢包,数据损坏,它都不能提供任何解决办法;
- IP协议只是将数据发送到了目标主机,但是应该由哪个应用程序来接受这个数据包呢?IP协议没有办法告诉我们。
因此传输层的作用就是为了实现以上两点目的。
传输层协议有 TCP 协议和 UDP 协议。TCP 协议是面向有连接的协议,也就是说在使用 TCP 协议传输数据之前一定要在发送方和接收方之间建立连接。一般情况下建立连接需要三步,关闭连接需要四步。
- TCP概述: TCP 协议是面向有连接的协议,还有数据重传、流量控制等功能,TCP 协议能够正确处理丢包问题,保证接收方能够收到数据,与此同时还能够有效利用网络带宽。然而 TCP 协议中定义了很多复杂的规范,因此效率不如 UDP 协议,不适合实时的视频和音频传输;
- UDP概述: UDP 协议是面向无连接的协议,它只会把数据传递给接收端,但是不会关注接收端是否真的收到了数据。但是这种特性反而适合多播,实时的视频和音频传输。因为个别数据包的丢失并不会影响视频和音频的整体效果。
IP 协议中的两大关键要素是源 IP 地址和目标 IP 地址。而刚刚我们说过,传输层的主要作用是实现应用程序之间的通信。因此传输层的协议中新增了两个要素:源端口号,目标端口号。再加上IP首部中的协议号,通过这五个信息,可以唯一识别一个通信。用一句话来概括就是:“源 IP 地址,目标 IP 地址,源端口号,目标端口号和协议号”这五个信息只要有一个不同,都被认为是不同的通信。
端口号
作用:用于区分同一台主机中正在通信的不同应用程序,因此也被称为程序地址。不同的端口用于区分同一台主机上不同的应用程序。假设你打开了两个浏览器,浏览器 A 发出的请求不会被浏览器 B 接收,这就是因为 A 和 B 具有不同的端口。端口号分为两种:
- 知名端口号:这种端口号是固定的,用于服务器程序,使用对应协议的程序就将端口号设为对应的数字。比如DNS的端口号就是53;
- 动态端口号:这种端口号是不固定的,用于客户端程序,客户端程序对端口号要求不高,只要该端口号在本机中唯一就行。
端口号 | 协议 |
53 | DNS |
80 | HTTP |
20 | FTP数据 |
21 | FTP控制 |
23 | SSH |
25 | SMTP |
502 | MODBUS |
TCP与UDP
TCP与UDP都作为传输层的协议,必然是有所区别的。下表是关于TCP和UDP的区别:
角度 | TCP | UDP |
是否连接 | 面向连接(发送数据前需要建立连接) TCP在传输前先发送连接请求和应答包,确定双方能够 正常传输后,才开始进行数据传输。 |
无连接(发送数据无需连接) UDP在发送数据之前,并不考虑对方能否接受到,甚至目的地址可能都是无效 |
是否丢包重试 | 实现了数据传输时各种控制功能,可以进行丢包的重发 控制,还可以对次序乱掉的分包进行顺序控制 |
不会进行丢包重试,也不会纠正到达的顺序 |
模式 | 流模式(面向字节流) TCP把数据看成一连串无结构的字节流,没有边界,一 段段传输构成了整个数据块。通过发送缓冲区和接受缓冲区来存储数据流。 |
数据报模式(面向报文) UDP数据报模式,每一个数据报都是一个独立的对象,有着指定的大小。 |
对应关系 | 一对一 | 支持一对一,一对多,多对一和多对多的交互通信 |
头部开销 | 最小20字节 | 只有8字节 |
可靠性 | 全双工非常可靠、无差错、不丢失、不重复、且按序到达 | 不保证可靠交付,不保证顺序到达 |
拥塞控制 | 有控制 更多详情 | 有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低 (对实时应用很有用,如IP电话,实时视频会议等) |
资源要求 | TCP程序结构较复杂,较多 | UDP程序结构简单,少 |
基于上表的区别,TCP与UDP具有不同的用途:
TCP:用于实现可靠传输的情况,文件非常重要,对网络拥堵有较高要求的情况;
UDP:
- 用于高速传输和实时性较高的场合(即时通信)。对于采用UDP的实时视频通信,如果出现丢包也只会出现短暂卡顿,但是如果采用TCP丢包后需要重发,会导致很长时间的卡顿;
- 包总量较少的通信(DNS),客户端较多;
- 广播通信。
TCP与UDP的首部
UDP首部
- 源端口号:表示发送端端口号,不需要时设为0;
- 目标端口号:表示接收端端口号;
- 包长度:表示整个UDP包的长度;
- 校验和:为了提供可靠的UDP首部和数据而设计,只要源IP地址,目标IP地址,源端口号,目标端口号,协议号有一个发生了篡改校验和都会不正确。
TCP首部
- 源端口号:发送端端口号;
- 目标端口号:接受端端口号;
- 序列号(Seq):发送数据时,表示发送数据的位置,发送完一次数据后,序列号的值都等于原来的序列号加上数据的长度;
- 应答号(Ack):用于接受端告诉发送端下次应该从哪个位置开始发送,表示前面的数据已经都收到了,Ack = Seq + 1;
- 数据偏移:实际就是TCP首部长度;
- 保留:一般设置为0,用于后续扩展;
- 控制位(标志位):长度为6,从左到右分别是URG,ACK,PSH,RST,SYN,FIN;
- 窗口大小:能够发送数据的最大值,为0时可以发送探测窗口;
- 校验和:与UDP校验和作用相同;
- 紧急指针:用于处理紧急情况;
- 选项:其他控制设置。
常见的控制位(标志位)的含义:
- URG:紧急指针(urgent pointer)有效,告诉接收TCP模块紧要指针域指着紧要数据;
- ACK:确认序号有效;
- PSH:接收方应该尽快将这个报文交给应用层,而不必等到缓冲区满时才传送;
- RST:重置连接,如果接收到RST位时候,通常发生了某些错误;
- SYN:建立一个新连接;
- FIN:断开一个连接。
如何实现可靠的UDP
之前提到UDP是不可靠的,但是在一些使用UDP的环境中,又想保证其有一定的可靠性,那么怎么才能实现可靠的UDP呢?
既然在传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。
也就是说,在应用层上实现确认机制、重传机制、窗口确认机制。如果你不利用Linux协议栈以及上层socket机制,自己通过抓包和发包的方式去实现可靠性传输,那么必须实现如下功能:
- 数据完整性 –> 加上一个16或者32位的CRC验证字段
- 乱序 –> 加上一个数据包序列号SEQ(编号)
- 丢包 –> 需要确认和重传机制,就是和Tcp类似的Ack机制
比如:
- 给数据包编号,按照包的顺序存储并发送;
- 接收端接收到数据包后检验验证字段和数据包编号,如果都正确,则发送确认信息给发送端,发送端接收确认数据以后再继续发送下一个包;如果接收端收到的数据包的编号不是期望的编号或者没有验证字段,则要求发送端重新发送。
参考文章:怎样实现UDP可靠传输。
目前有如下开源程序利用udp实现了可靠的数据传输,分别为RUDP、RTP、UDT。
- RUDP:RUDP 提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的情况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制允许 TCP 方式下的流控制行为;
- RTP:实时传输协议(RTP)为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务;这两种协议都提供了传输层协议的功能。但是 RTP 可以与其它适合的底层网络或传输协议一起使用。如果底层网络提供组播方式,那么 RTP 可以使用该组播表传输数据到多个目的地;
- UDT:基于UDP的数据传输协议(UDP-basedData Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。由于UDT完全在UDP上实现,它也可以应用在除了高速数据传输之外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。
参考文章:udp如何实现可靠性传输?。
这边是有一份面试总结的链接:面试总结--网络。