【网络基础】网络协议传输层UDP和TCP

UDP

解包和分用

解包(解析数据包)

  1. 捕获数据包:首先,接收端的网络栈捕获UDP数据包。
  2. 检查目的端口:接收端检查数据包头部的目的端口,以确定哪个应用程序应该接收该数据包。
  3. 验证校验和:接收端可能会计算并验证数据包的校验和,以检测数据在传输过程中是否出现错误。如果校验和不匹配,数据包通常会被丢弃。
  4. 提取数据载荷:如果校验和正确,接收端提取数据载荷并将其传递给相应的应用程序。

分用(Demultiplexing)

分用是指将接收到的数据包定向到正确的应用程序或进程的过程。

  1. 端口号匹配:分用主要依赖于端口号。每个UDP数据包都有一个目的端口号,接收端使用这个号码将数据包路由到绑定了该端口号的应用程序。
  2. 应用程序处理:应用程序监听其绑定的端口,接收到数据包后,它会根据自己的逻辑和协议来处理数据。

认识知名端口号

UDP的特点

TCP

报头的理解

字段

报头理解

tcp的可靠性

超时时间

三次握手

四次挥手

FIN_WAIT状态

FIN_WAIT状态分为两个子状态:FIN_WAIT_1FIN_WAIT_2

  1. FIN_WAIT_1

    • 这个状态发生在已经发送了FIN段的一方(通常是客户端)关闭TCP连接的初始请求后,正在等待对端的ACK确认。
    • 如果收到ACK,状态转移到FIN_WAIT_2
  2. FIN_WAIT_2

    • 在这个状态下,发送FIN的一方已经接收到ACK确认,并等待对端的FIN请求,表明对端也准备关闭连接了。

CLOSE_WAIT状态

当一个TCP端点接收到对端的FIN请求,它会发送ACK确认并进入CLOSE_WAIT状态。在CLOSE_WAIT状态下,TCP端点等待本地用户进程执行关闭操作,发送自己的FIN段。

流量控制

滑动窗口

刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段.

这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候.

拥塞控制

虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题.

因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的.

TCP引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据;

慢启动

延迟应答

如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小.

假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;

但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;

在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;

如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;

一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;

那么所有的包都可以延迟应答么? 肯定也不是;

数量限制: 每隔N个包就应答一次;

时间限制: 超过最大延迟时间就应答一次;

具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms;

捎带应答

在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 "一发一收" 的. 意味着客户端给服务器说了 "How are you", 服务器也会给客户端回一个 "Fine, thank you";

那么这个时候ACK就可以搭顺风车, 和服务器回应的 "Fine, thank you" 一起回给客户端

面向字节流

创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;

调用write时, 数据会先写入发送缓冲区中;

如果发送的字节数太长, 会被拆分成多个TCP的数据包发出;

如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或者其他合适的时机发送出去;

接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;

然后应用程序可以调用read从接收缓冲区拿数据;

另一方面, TCP的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工

由于缓冲区的存在, TCP程序的读和写不需要一一匹配, 例如:

写100个字节数据时, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节;

读100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100个字节, 也可以一次read一个字节, 重复100次;

粘包问题

首先要明确, 粘包问题中的 "包" , 是指的应用层的数据包.

在TCP的协议头中, 没有如同UDP一样的 "报文长度" 这样的字段, 但是有一个序号这样的字段.

站在传输层的角度, TCP是一个一个报文过来的. 按照序号排好序放在缓冲区中.

站在应用层的角度, 看到的只是一串连续的字节数据.

那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.
那么如何避免粘包问题呢? 归根结底就是一句话, 明确两个包之间的边界.

对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可;

对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;

对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只要保证分隔符不和正文冲突即可);

思考: 对于UDP协议来说, 是否也存在 "粘包问题" 呢?

对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层. 就有很明确的数据边界.

站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会出现"半个"的情况.

TCP异常情况

进程终止 : 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
机器重启: 和进程终止的情况相同.
机器掉电/网线断开 : 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.

另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ断线之后, 也会定期尝试重新连接.

基于TCP应用层协议

HTTP

HTTPS

SSH

Telnet

FTP

SMTP

TCP/UDP对比

我们说了TCP是可靠连接, 那么是不是TCP一定就优于UDP呢? TCP和UDP之间的优点和缺点, 不能简单, 绝对的进行

比较

TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;

UDP用于对高速传输和实时性要求较高的通信领域, 例如, 早期的QQ, 视频传输等. 另外UDP可以用于广播;

归根结底, TCP和UDP都是程序员的工具, 什么时机用, 具体怎么用, 还是要根据具体的需求场景去判定

相关推荐
gywl2 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
WTT00112 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
_oP_i3 小时前
HTTP 请求Media typetext/plain application/json text/json区别
网络协议·http·json
杨德杰3 小时前
QT网络(一):主机信息查询
网络·qt
007php0073 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
yang_shengy3 小时前
【JavaEE】网络(6)
服务器·网络·http·https
OkeyProxy4 小时前
HTTP、HTTPS和SOCKS5代理協議
网络协议·https·云计算·代理服务器·海外ip代理
zquwei4 小时前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
Aimin20225 小时前
路由器做WPAD、VPN、透明代理中之间一个
网络
群联云防护小杜5 小时前
如何给负载均衡平台做好安全防御
运维·服务器·网络·网络协议·安全·负载均衡