TCP与UDP区别详解
计算机与其余网络设备相互通讯,通讯的双方在发送和接收数据包时必须基于相同的规则(例如:如何找到通讯目标、如何发起通讯、如何结束通讯等规则都须要事先肯定),咱们将这种规则称为协议(Protocol)。html
TCP/IP协议簇是 Internet 的基础,其是一系列网络协议的总称,例如:TCP、UDP、IP、FTP、HTTP、ICMP、SMTP等都属于TCP/IP协议族内的协议。
这些协议在计算机网络中自下而上被划分为四层:链路层、网络层、传输层和应用层。缓存
- 链路层:
负责发送和接收ARP/RARP报文;
- 网络层:
该层包含IP协议、RIP协议(Routing Information Protocol),主要负责数据包在主机之间的传输
;
- 传输层:
主要负责定位处理数据的具体进程并转发数据
(TCP协议提供可靠的数据流运输服务,UDP协议提供不可靠的数据服务);
- 应用层
负责向用户提供应用程序,好比HTTP、FTP、Telnet、DNS、SMTP等;

在网络体系结构中网络通讯的创建必须是在通讯双方的对等层进行,不能交错。
在整个数据传输过程当中,数据在发送端通过各层时都要附加上相应层的协议头和协议尾(仅链路层须要封装协议尾)。网络
UDP 与 TCP 两种传输协议是 TCP/IP 协议簇的核心成员。数据结构
1、UDP
UDP(User Datagram Protocol)全称是用户数据电报协议,是一种无链接的协议,提供不可靠的用户数据报服务,1980 年发布的 RFC 768 定义了 UDP 协议。tcp
UDP数据结构.net
UDP数据结构以下图所示:
计算机网络
UDP 协议头中只包含 4 个字段:源端口、目的端口、UDP长度、UDP校验码,其中每个字段都占 16 位,即 2 字节,共8个字节。debug
- 源端口
发送方进程的端口号,接收方可使用该字段(不必定准确)向发送方发送信息(范围0-65535);
- 目的端口
数据接收方的端口号(范围0-65535);
- UDP长度
协议头和数据报中数据长度的总和,表示整个数据报的大小;
- UDP校验码
使用 IP 首部、UDP 首部和数据报中的数据进行计算,接收方能够经过校验码验证数据的准确性,发现传输过程当中出现的问题;
UDP首部数据举例3d
常见的 DNS 协议就可使用 UDP 协议获取域名解析的结果:code
0000 ff 7c 00 35 00 23 c2 6e
上述 UDP 首部中四个字段对应的值以下:
- 源端口 0xff7c = 65404
- 目的端口 0x0035 = 53
因为 DNS 协议使用的端口是 53,因此目的端口就是 53
- UDP长度 0x0023 = 35
- UDP校验码 0xc26e
UDP在数据传输中的位置
这里咱们能够将应用到应用之间的传输过程分红两个部分:
主机到主机的数据传输
和主机到应用的数据转发
。
- UDP 协议首部的
目的端口号
用于定位处理数据的具体进程并转发数据;
- UDP 协议底层的网络层IP协议(Internet Protocol)会负责数据包在主机之间的传输;
咱们说 UDP 协议是传输层协议,可是真正在主机间完成数据传输
工做的是 IP 协议
,UDP 协议
只起到了定位具体进程
的做用。
UDP数据传输的特色
- 面向无链接
UDP 不须要与 TCP同样在发送数据前进行三次握手创建链接,UDP想发数据就直接发送了;而且UDP只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操做。
- 不可靠
首先不可靠性体如今无链接上,通讯都不须要创建链接,想发就发,这样的状况确定不可靠的;而且收到什么数据就传递什么数据,也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据;
再者网络环境时好时坏,可是 UDP 由于没有拥塞控制,一直会以恒定的速度发送数据;即便网络条件很差,也不会对发送速率进行调整,这样实现的弊端就是在网络条件很差的状况下可能会致使丢包,可是优势也很明显,在某些实时性要求高的场景(好比直播、电话会议等)就须要使用 UDP 而不是 TCP;
- 单播、多播、广播功能
因为 UDP 不会创建链接,所以它能够给任何人传递数据,不止支持一对一的传输方式,一样支持一对多、多对多、多对一的方式;
- UDP是面向报文的
发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层(UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界);
- 头部开销小,传输数据高效
UDP 的头部开销小,只有八字节,在传输数据报文时是比较高效的(在某些实时性要求高的场景,例如直播、电话会议、媒体传输等场景常用 UDP协议);

2、TCP
TCP(Transmission Control Protocol)协议全称是传输控制协议,是一种面向链接的、可靠的、基于字节流的传输层通讯协议,由RFC 793定义。
当用户查看网页或电子邮件时,但愿看到的内容完整且顺序正确,不丢失任何内容;当下载文件时,但愿得到的是完整的文件,而不只仅是文件的一部分;以上应用场景的传输层协议都可采用TCP协议。
TCP数据结构

- 源端口、目标端口
发送方进程的端口号,数据接收方的端口号(范围0-65535);
- 序号
主要是为了解决乱序问题(编好号才知道哪一个先来,哪一个后到);
- 确认序号
发出去的包应该有确认,这样能知道对方是否收到,若是没收到就应该从新发送,这个解决的是不丢包的问题;
- 状态位
SYN 是发起一个连接,ACK 是回复,RST 是从新链接,FIN 是结束链接(TCP 是面向链接的,所以须要双方维护链接的状态,这些状态位的包会引发双方的状态变动);
- 窗口大小
TCP 要作流量控制,须要通讯双方各声明一个窗口,标识本身当前的处理能力;
TCP三次握手
TCP协议发送数据以前必须在通讯的两端创建链接,创建链接的方法是TCP三次握手
:

- 第一次握手
客户端向服务端发送链接请求报文;请求发送后,客户端便进入 SYN-SENT 状态;
- 第二次握手
服务端收到链接请求报文后,若是赞成链接,则会发送一个应答,发送完成后便进入 SYN-RECEIVED 状态;
- 第三次握手
当客户端收到链接赞成的应答后,还要向服务端发送一个确认报文;客户端发完这个报文后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时链接创建成功。
为何 TCP 创建链接须要三次握手,而不是两次?
TCP既要保证数据可靠传输,又要提升传输的效率,而用三次(客户端与服务端发送的报文都获得了响应,通讯双方全都有来有回
)偏偏知足了以上两方面的需求!

TCP四次挥手
TCP断开链接,也被称为四次挥手:

- 第一次挥手
A:B,我不玩了
客户端A
向服务端B
发送链接释放请求;
- 第二次挥手
B:OK,A不玩了,知道了
服务端B 收到链接释放请求后,发送 ACK 包,并进入 CLOSE_WAIT 状态;
此时服务端B再也不接收客户端A发送的数据,但服务端B 若此时还有没发完的数据会继续发送;
- 第三次挥手
B:A,我也不玩了,拜拜
服务端 B 向 A 发送链接释放请求,而后 B 便进入 LAST-ACK 状态;
- 第四次挥手
A:OK,B不玩了,拜拜
客户端A 收到释放请求后,向 服务端B 发送确认应答,此时 客户端A 进入 TIME-WAIT 状态;
客户端A的 TIME-WAIT状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。
TCP协议的特色
相比与UDP协议,TCP协议拥有面向链接、保证顺序、可靠传输、提供拥塞控制
等特色。
为了保证顺序性,每一个TCP数据包都有一个序号ID
,在创建链接的时候会商定起始 ID 是什么,而后按照 ID 一个个发送;
为了保证不丢包,须要对发送的包都要进行应答,这里应答不是一个一个来的,而是会应答某个以前的 ID,表示都收到了,这种模式成为累计应答
;
为了记录全部发送的包和接收的包,须要发送端
和接收端
分别缓存这些记录。
TCP发送端
的缓存里是按照数据包的 序号ID 一个个排列,根据处理的状况分红四个部分:
- 发送而且确认的;
- 发送还没有确认的;
- 没有发送等待发送的;
- 没有发送而且暂时不会发送的;

在 TCP 协议中接收端会给发送端报一个窗口大小Advertised Window
,这个窗口大小等于上面的第2、第三部分加和
,超过这个窗口接收端处理不过来,暂时不能继续发送;
上图TCP发送端缓存队列中:
- 一、二、3 已发送并确认;
- 四、五、六、七、八、9 都是发送了还没确认;
- 十、十一、12 是还没发出的;
- 1三、1四、15 是接收方没有空间,不许备发的。
TCP接收端
缓存内容类型以下:
- 接收而且确认过的;
- 还没接收,立刻就能接收的;
- 还没接收,也没法接收的;

上图TCP接收端缓存队列中:
- 一、二、三、四、5 是已经完成 ACK ;
- 六、7 是等待接收的,八、9 是已经接收尚未 ACK 的;
- 十、十一、12 、1三、1四、15 是暂时没法接收的;
TCP发送端、接收端
当前的状态以下(依据以上两个图):
- 一、二、3 没有问题,双方达成了一致;
- 四、5 接收方响应 ACK 了,可是发送方还没有收到;
- 六、七、八、9 确定都发了,并且八、9 已经到了,但六、7 还没有收到,出现了乱序,缓存着暂没法 ACK;
根据这个例子能够知道顺序问题和丢包问题都有可能存在:
假设4的ACK响应发送端收到了,5的ACK丢了;六、7的数据包丢了,该怎么办?
- 一种方法是超时重试,即对每个发送了可是没有 ACK 的包设定一个定时器,超过了必定的事件就从新尝试;这个重试时间必须大于往返时间,但也不宜过长,不然超时时间变长,访问就变慢了;
例如:过一段时间,五、六、7 的ACK都超时了,发送端就会从新发送;接收方发现 5 原来接收过 因而丢弃 5,六、7收到了发送 ACK;
- 另外一个快速重传的机制,即当接收方接收到一个序号大于指望的报文段时,就检测数据流之间的间隔,因而发送三个冗余的 ACK,客户端接收到以后,知道数据报丢失,因而重传丢失的报文段;
例如:接收方发现 六、八、9 都接收了,可是 7 没来(7丢了),因而发送三个 6 的 ACK,要求下一个是 7;客户端接收到 3 个ACK,就会发现 7 丢了,立刻重发。
参考
UDP—RFC768:
https://tools.ietf.org/html/rfc768
TCP—RFC973:
https://tools.ietf.org/html/rfc793
Stackoverflow: UDP checksum calculation, Sep 2017
https://stackoverflow.com/questions/1480580/udp-checksum-calculation
百度百科—UDP:
https://baike.baidu.com/item/UDP/571511?fr=aladdin
百度百科—TCP:
https://baike.baidu.com/item/TCP/33012?fr=aladdin
TCP 和 UDP 的区别:
http://www.javashuo.com/article/p-kbkappoe-hc.html
一文搞懂TCP与UDP的区别
https://www.cnblogs.com/fundebug/p/differences-of-tcp-and-udp.html
========== THE END ==========
