《 传输层协议精解:TCP的三次握手与UDP的无连接特性全解析》

**前引:**当你在手机上刷着高清直播,画面流畅无延迟;转头用办公软件传一份重要报告,即便网络波动也能确保文件完整------这两种截然不同的网络体验,背后藏着传输层两大核心协议的"功劳":TCP与UDP。前者像严谨的"快递员",全程跟踪、确认签收,绝不丢失包裹;后者则是高效的"急行军",直奔目标、无需等待,用速度优先完成任务。看似功能对立的它们,共同构成了网络传输的基础框架。本文将带你走进传输层的世界,剖析TCP与UDP的核心差异、设计逻辑,以及如何在不同场景中做出最优选择!

目录

【一】UDP协议

(1)报文结构认识

(2)通信特点

【二】TCP协议

(1)基本概念

(1)缓冲区

(2)6位标志位

(3)32位序号/确认序号

(4)16位窗口大小

(5)16位紧急指针

(6)16位检验和

(7)4位首都长度

(2)应答机制

(3)超时重传机制

(4)捎带应答机制

(5)三次握手+四次挥手

三次握手:

四次挥手:

(6)滑动窗口

(7)流量控制

(8)拥塞控制

(9)延迟应答

(10)面向字节流

(11)粘包问题


【一】UDP协议

(1)报文结构认识

我们在进入网络时知道,每层的报文都需要加上对应的报头,UDP的报文格式如下结构:

16位源端口号:客户端的端口

16位目的端口号:服务器对应进程的端口

(一个进程可以绑定多个端口,但是一个端口只能被一个窗口绑定)

16位UDP长度:整个数据报(UDP⾸部+UDP数据)的最⼤⻓度

16位UDP检验和:判断报文是否可靠

(2)通信特点

(1)不需要和对方确立联系,知道对方的IP和端口,直接开始传数据

(2)没有确认机制,即应答机制,不知道本次数据传输是否被对方接收

(3)面向数据包:好比一个大小固定的快递盒

(4)没有发送缓冲区,只有接收缓冲区(无法保证数据顺序,缓冲区满了就会直接丢弃)

【二】TCP协议

(1)基本概念

首先我们从最外面的缓冲区开始讲解,然后进入报文里面的端口大小,首都长度这些!

(1)缓冲区

双方如果都采用TCP协议作为传输协议,那么单方都具有接收缓冲区和发送缓冲区:

**注意:**缓冲区的数据都是报文格式的

(2)6位标志位

这里先只输出每个标志位的作用,后面会再次进行理解:

ACK:确认对方是否收到

PSH:提⽰接收端应⽤程序⽴刻从TCP缓冲区把数据读⾛

RST:对⽅要求重新建⽴连接;我们把携带RST标识的称为复位报⽂段

SYN:请求建⽴连接;我们把携带SYN标识的称为同步报⽂段

FIN:通知对⽅,本端要关闭了,我们称携带FIN标识的为结束报⽂段

(3)32位序号/确认序号

TCP的每个报文都是如下形式,可以没有数据,但至少有TCP报头:

TCP将每个数据以字节为单位都进行了编号,例如:1001,1000.........

当发送第一批数据的时候,假设是1000字节,那么发送方的32位序号就是1000,如果正常接收方正常接收,那么接收方的32位确认序号就是1001。注意:服务端也可能在给客户端发送消息

即表示发送方已经完成了1000以内的所有数据发送,1001表示接收方完成1001之前全部数据接收

(4)16位窗口大小

含义:自己接受缓冲区中的剩余空间大小

(5)16位紧急指针

含义:标志紧急数据,需要被立刻处理的

(6)16位检验和

含义:发送端填充,表示数据大小(不算报头),通常由接收端进行检验

(7)4位首都长度

在TCP中,存在度量"单位数"------4字节,TCP报文会一般会将本次报头存在多少"单位数"放在4位首都长度,比如4位首都长度为5,那么报头的大小就是4*5=20字节,假设报文总大小是100字节,100字节减去报头20字节,就是(数据+选项)大小,方便快速将数据和报头分离!

(2)应答机制

含义:向对方发送信息,对方会回你,即应答机制

(3)超时重传机制

假设现在客户端和服务端正在进行通信,那么可能存在如下情况:

(1)客户端的数据在传输过程中丢包

(2)客户端的数据传给了服务端,但是服务端的反馈丢包

(3)双方都正常,但是自己网络导致数据单方拿不到数据

在通信过程中,一般都是客户端主动向服务端发起请求,那么就可能出现上面的几种非正常通信情况,此时,会存在"超时重传"机制,当发送给对方的数据在一个规定时间,比如超过500ms(存在差异),那么发送方就会重新发送数据------即规定时间未收到回复,将重新发送;如果时间太长还未收到回复,会直接断开连接

但是这样就会出现一个新的问题:对方可能接收的是重复数据

此时因为"序号(例如1000)"的存在,会达到去重的效果,这里需要"滑动窗口",我们后面理解!

(4)捎带应答机制

含义:将确认是否收到(ACK)和要发送的数据一起发送给对方,减少频繁发送提高效率,例如:

(5)三次握手+四次挥手

6位标志位的用法其实是用来标签不同的报文类型,比如客户端和服务端有建立连接、确认对方是否收到、是否和对方断开连接.......不同的报文类型,它们可能只有报头!

三次握手:

(1)客户端向服务端发起连接请求 SYN

(2)服务端回复:确认请求(ACK)+尝试和客户端发起请求(SYN)

(3)客户端回复:确认请求(ACK)

注意:三次握手中的第二次,其实是使用了"捎带应答"机制,本质上也算是四次握手!

为什么存在应答机制,客户端最后一次方式ACK确认之后,服务端不用回?

因为在三次握手中,双方已经确认是否可以正常通信,没有必要执行第四次,否则会陷入问答循环

第三次握手如果失败会出现什么情况?

前两次握手,服务端和客户端一问一答有回应,若失败,客户端会执行超时重传机制;但是如果客户端在第三次向服务端发送ACK确认应答之后,服务端没有收到第三次客户端的ACK呢?客户端会自以为已经完成三次握手,当客户端再发送数据时,服务端会响应RST(要求对方重新建立连接)

这三次握手和应用层的接口有什么关系?

客户端的connect()和服务端的listen()其实就对应前两次握手,第三次握手是connect()的返回结果;如果客户端一直没有收到对方的ACK应答,就会卡在一个名为"中间队列"中;当三次顺利完成,此时accept()会给这个客户端返回新的文件描述符,即三次握手是在accept()之前的,accept()也会形成一个队列,名为"全链接队列",服务端处理完毕上一批客户端,立马从"全链接队列"开始拿新的客户端,队列的存在也是一种提高效率的行为

四次挥手:

(1)客户端可能有数据给服务端,服务端应答ACK

(2)服务端可能有数据给客户端,客户端应答ACK

(3)客户端发起断连请求,服务端应答ACK

(4)服务端发起断连请求,客户端应答ACK

**TCP协议规定:**主动断开连接的那一方,会进入TIME_WAIT状态,等待两个MSL的时间后才能回到CLOSED状态,MSL的大小可以使用如下指令查看:cat /proc/sys/net/ipv4/tcp_fin_timeout

为什么要有TIME_WAIT状态?

(1)保证双方之前的迟到的、出现错误的报文全部处理完毕

(2)同时也是在理论上保证最后⼀个报文可靠到达,假设最后一个ACK丢失,服务器就会重发, 此时虽然客户端已经断开,但是它的TCP还在(IP端口还在使用)就可以对服务器做出应答

如何解决TIME_WAIT状态导致无法立刻重复绑定?

使⽤ setsockopt ()设置 socket 描述符的选项 SO_REUSEADDR 为 1

含义:表⽰允许创建端⼝号相同 但IP地址不同的多个 socket 描述符

如何解决服务端大量CLOSE_WAIT状态?

及时使用close()关闭对应的文件描述符,服务器才会向客户端发送断连请求

(6)滑动窗口

在上面我们学过"应答"机制,即发生方给接收方的报文,接收方都要有应答,即一对一,但是频繁的一对一发送与应答难免出现效率问题,如果中间网络很拥堵呢?或者对方没有接收到呢?

那么最佳实践方案:一次性发送多条数据,对应多次应答。即滑动窗口

在发送缓冲区中其实是存在数据分组的:已发送已确认、已发送未确认、未发送

那么我们再次细分,来理解滑动窗口:缓冲区中类似数据存储数据,通过下标访问

那么每次就可以发送滑动窗口包含的数据:对方再回复对应的序号即可

(注意:序号(如1001,2001......)表示之前的报文已经收到

滑动窗口是如何移动的?

假如现在要发送0~3000的报文,但是1000~2000的丢了,如图:

满足如下规律:左边由是否确认应答决定(不会向左移动),右边受限于对方窗口大小,动态调整

滑动窗口如何解决各种情况的?

情况1:数据包已收到,但是应答丢了,如图。此时可以通过后面的应答报文知道情况

情况2:数据包直接丢了,如图。此时没有接收方在1001~2000的应答ACK**,如果发送方连续三次接收到相同的应答ACK,那么就会重新发送对应的报文**,例如:发送方发送1000~7000的报文

此时1000~2000的报文丢了,接收方就只会返回2001,发送方连续三次收到的话,就会重新发送,此时接收方再返回7001的应答,因为之前部分报文已经存到了接收方的缓冲区中

(7)流量控制

当客户端和服务端在三次握手的时候,双方会协商窗口大小,表示适合对方的一次性发送的数据控制大小,也就是流量控制------一般在报文中的"16位窗口大小"会告诉对方

滑动窗口会根据对方的窗口反映情况动态变化发送的数据大小,例如:

(8)拥塞控制

避免问题:网络拥堵造成数据大量丢失或者大量延迟

解决办法:慢启动发送方开始会发送少量的数据,查看当前网络情况,再根据情况增加数据

如果发生大量数据的时候,网络突然波动,那么就会重新试探网络的情况,重新开始热发送

引入名词:拥塞窗口,刚开始定义拥塞窗⼝⼤⼩为1,每次收到⼀个ACK应答,拥塞窗⼝加1

每次发送数据包的时候,将 拥塞窗⼝ 和 接收端主机反馈的窗⼝⼤⼩ 做⽐较,取较⼩的值作为实际发送的窗⼝------min(拥塞窗口、接收端主机反馈的窗口大小)

(9)延迟应答

如果接收数据的主机⽴刻返回ACK应答,这时候返回的窗⼝可能⽐较⼩

TCP存在优化方案:我感觉就是(捎带应答的进阶版,哈哈哈!)

只要网络不拥堵,那么窗⼝越⼤,⽹络吞吐量就越⼤,传输效率就越高

(10)面向字节流

**全双工:**对于TCP协议,既可以读数据,也可以写数据(存在发送和接收两个缓冲区)

**面向字节流:**数据的读取和发送不需要一一匹配,可以发100次/字节,也可以只读一次/100字节

(11)粘包问题

什么是粘包问题?应用层获取到的数据报文并不是完整的,传输层只负责拿报文,可能是1.5个...

解决本质:通过应用层自定义协议,划分出一个个报文

如何解决粘包问题:定长报文(例如给数据包固定在10字节)

使用特殊字符区分

在发送数据之前,在数据前面先发送数据大小(例如"5字节""Hello")

相关推荐
科技块儿2 小时前
使用强大的离线IP地址定位库IP数据云获取数据信息
网络·tcp/ip·php
(Charon)6 小时前
[网络编程] 基于 DPDK 的 UDP 报文收发实现
网络·网络协议·udp
..过云雨6 小时前
HTTP 协议深度解析:请求/响应、报头、正文的核心原理与实战
网络·网络协议·tcp/ip·计算机网络·http
Mintopia7 小时前
🚀 HTTP/2 多路复用技术全透视
网络协议·http·https
nvd118 小时前
从 SSE 到 Streamable HTTP:MCP Server 的现代化改造之旅
网络·网络协议·http
小蜗的房子8 小时前
Oracle 19C RAC Public IP单网卡改为bond模式操作指南
运维·网络·数据库·sql·tcp/ip·oracle·oracle rac
UrSpecial11 小时前
IPv6网络协议
网络·网络协议
小小ken11 小时前
ubuntu添加新网卡时,无法自动获取IP原因及解决办法
linux·网络·tcp/ip·ubuntu·dhcp
夏侯羽11 小时前
HTTPS 是怎么工作的
网络协议·http·https