| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 计算机网络 - TCP协议与UDP协议 -> 正文阅读 |
|
[网络协议]计算机网络 - TCP协议与UDP协议 |
UDP协议 UDP协议UDP协议: UDP报文长度为2个字节, 也就是UDP报文的位数最大为65535 一个完整的UDP报文格式: ??长度指UDP数据报的长度, 范围为0~65535, 要想使用UDP协议表示一个更大的数据, 就需要在应用层对数据进行分包, 将数据拆成多个部分, 然后通过多个UDP数据报进行发送, 再让接收方将数据重新进行拼接. 但这种方法又需要考虑更多的问题, 例如出现丢包情况, 或者包的接收顺序发生了改变, 因此, 我们不推荐这种做法. ??如果报文过长, UDP报文难以满足需求, 就需要通过报文长度可变的TCP协议来传输数据. TCP协议TCP报文格式: TCP协议的可靠传输机制确认应答确认应答:保证可靠传输的和新机制 ??接收方接收到消息之后, 向发送方发送一个应答报文(ACK, acknowledge)表示自己已经接收到消息, 而在网络中, 数据的发送十分频繁, 可能会出现数据先发后至(数据的发送顺序与接收顺序不一致)的情况, TCP报文中的32位序号就记录了报文中每个字节的发送序号, 32位确认序号记录了当前的应答报文是针对哪一条报文的应答, 有效解决了先发后至问题. ??要注意的是, TCP协议是针对字节来进行编号的, 例如第一个字节记为编号1, 第一千个字节记为编号1000等. 一次完整的确认应答的方式为: 超时重传确认应答是当网络环境正常时, 接收方向发送方发送应答报文, 而超时重传机制的应用场景主要是网络传输过程中出现丢包问题时. 例如, 当主机A向主机B发送了一条报文, 此时A有两种可能无法收到B发来的应答报文:
对于发送方来说, 无法区分这两种情况, 因此, 只要发送方没有接收到应答报文, 在等待一段时间后, 就会继续向接收方发送报文, 这就是超时重传机制. 如果是上面的第二种情况, 此时接收方收到了两条相同的报文, 操作系统内核就会通过TCP协议来执行一次去重操作. 去重操作的具体步骤为:
注意:去重操作是在操作系统内核中执行的, 因此, 应用程序无法感知到接收方发来的数据是否为重复数据 ??发送方的超时重传也不是一定成功的, 存在多次传输全部失败的情况(例如网络环境非常差, 已经无法正常通信), 在这种情况下, TCP首先会持续降低传输频率(也就是重传的时间间隔越来越长), 如果重传操作一直失败(也就是发送方始终无法收到接收方发来的应答报文), 发送方就会放弃传输, 并与接收方断开连接. ??对于主流的操作系统来说, 发送失败时进行超时重传的次数以及两次重传之间的时间间隔并非固定, 而是可以修改的. 连接管理如何建立连接(三次握手)客户端和服务器之间通过三次交互, 完成建立连接的过程. 注意:建立连接请求的一方是客户端(服务器无法主动向客户端建立连接请求) 建立连接请求: SYN是TCP报文中六个标志位的第五位, 如果SYN=1, 表示当前报文是一个同步报文段, 证明发送方正在请求与接收方建立连接 第二次握手:服务器收到连接请求之后, 向客户端发送ACK确认报文段, 并将该报文中的SYN置为1 ACK是六个标志位的第二位, 如果ACK=1, 表示这个报文是一个确认报文段(也就是应答报文). 服务器在应答报文中将SYN置为1, 表明服务器也要向客户端请求建立连接 第三次握手:客户端接收到服务器发来的报文, 并对服务器的请求作出应答, 发送一个应答报文(ACK=1), 允许服务器与自己建立连接. 至此, 客户端与服务器的三次交互完成, 代表两者成功建立连接. 三次握手的作用是什么?
第一次握手:检测发送方的发送能力 ??客户端与服务器建立连接之后, 操作系统内核中就会使用一定的数据结构来保存连接相关的信息, 其中最重要的也就是建立连接相关的五元组(源IP, 目的IP, 源端口, 目的端口, 协议类型), 此后, 如果连接中断, 这些数据也就变得不再有意义, 此时, 就需要通过四次挥手来释放这些系统资源. 如何中断连接(四次挥手)三次握手只能由客户端主动发起, 而四次挥手可以由客户端发起, 也可以由服务器发起. 四次挥手与三次握手的目的不同(三次握手是为了确保通过TCP协议实现可靠传输, 四次握手是为了释放系统资源), 但过程是十分相似的. 四次挥手的过程如下: 四次挥手能否变为三次挥手? ??服务器向客户端发送ACK和FIN的顺序是不同的, 服务器向客户端发送的ACK由操作系统内核负责, 一旦服务器收到客户端发来的FIN, 就会立刻返回一个ACK, 而FIN是由用户代码负责(只有代码中调用了socket.close()方法时才会触发FIN), 如果这两个操作的时间间隔非常小, 则有可能进行合并, 反之则无法进行合并. 滑动窗口滑动窗口:在保证可靠性的前提下尽量提高传输效率 有两台主机A和B, A向B发送数据, 如果不采用滑动窗口机制: ??由于确认应答机制的存在, 主机A向主机B发送下一条数据时需要等待B的应答报文, 这种传输效率非常低下, 因此, 我们需要通过滑动窗口机制来提高数据的发送效率: ??如果每次发送的数据为N, 则N为滑动窗口的窗口大小, 所谓"滑动", 就是说并不需要收到所有报文的ACK, 而是收到第一个ACK之后就继续发送下一组数据. ??例如, 上图中主机A先发送了四组数据, 当A收到1到1000的应答报文时, 就立刻发送下一组数据(也就是4001到5000), 等再次收到1001到2000的应答报文之后, 继续发送5001到6000. ??滑动窗口的窗口越大, 可以认为传输速率越快.(窗口越大, 同一时间内等待的ACK就越多, 总的等待ACK的时间就减少) 在滑动窗口的背景下, 如果出现丢包问题, 该如何解决呢? 丢包分为两种情况:
??这种情况不需要主动处理, 只需要通过后续收到的ACK进行确认即可, 例如, 发送方没有收到ACK1001, 但是收到了2001, 那就说明前面发送的数据没有问题, 只是ACK1001丢失(收到ACK2001的意思是:2001之前的所有数据都已接收到)
流量控制??上面提到了, 滑动窗口越大, 数据的传输速率越高, 但是, 如果一次同时发送的数据太多, 接收方难以同时处理, 此时接收方就会丢弃新接收到的数据, 后面发送方又会重新发送这些数据, 这就得不偿失了, 因此, 需要通过流量控制处理数据流量的发送数. 流量控制的关键, 就是衡量接收方的处理速度. ??接收方在接收数据时会将数据存入接收缓冲区中, 这样的数据接收机制类似于生产者 - 消费者模型, 发送方发送数据, 接收方将数据存入接收缓冲区中, ??TCP报文中存在16位窗口大小, 当接收方向发送方发送应答报文时, 通过这个窗口大小来告知发送方当前剩余空间的大小. ??如果窗口大小为0, 代表此时剩余空间已满, 发送方不应该再发送数据, 但是, 随着接收方处理数据, 缓冲区中的数据又会逐渐减少, 此时, 又需要发送方发送数据, 这样, 就达到了一个动态平衡的效果. ??发送方在接收到窗口大小为0的ACK之后, 就会停止发送数据, 那么, 发送方什么时候该继续发送数据呢? ??发送方每隔一段时间, 就会向接收方发送一个探测报文, 这个报文内部没有任何数据, 仅用于获取接收方最新的窗口大小的消息. 拥塞控制??数据传输的速度不仅取决于接收方的处理能力, 也取决于发送方和接收方之间链路的传输能力. 拥塞控制主要衡量的就是发送方到接收方整个链路之间的拥塞情况. ??拥塞控制的处理方案, 就是通过实验的方式, 逐渐调整发送速度, 找到一个合适的范围, 具体做法为: ??首先,发送方以一个比较小的窗口来发送数据, 如果数据比较流畅地到达, 就逐渐增大窗口的大小, 如果出现丢包现象, 就证明通信链路出现了拥堵, 此时再减小窗口. ??通过反复的增大/减小窗口, 就找到了窗口大小的一个合适的范围, 拥塞窗口在这个范围内不断变化, 以达到"动态平衡".
??最开始时, 实际的窗口大小非常小, 此时可以通过指数式的增长快速增长到极限值. 之后开始线性增长, 增长到一定程度就会开始丢包, 一旦丢包, 发送方就会让窗口变小(回归初识窗口大小), 继续重复刚才的指数增长和线性增长的过程.
延时应答??流量控制是希望数据不要发送地过快, 延时应答是在这个基础上尽可能地让窗口更大. ??具体策略为:当发送方向接收方发送探测报文时, 接收方不会立即回答, 而是先处理一部分接收缓冲区中的数据, 让然后返回给发送方一个更大的窗口大小, 来让发送方尽可能多地发送数据. 延时应答就是在发送速度有限的情况下, 尽可能地让发送方多发送数据. 捎带应答??由于延时应答的存在, 接收方在收到报文时, 不会立即返回ACK, 那么, 如果接收方也要向发送方发送报文, 这条报文和延时发送的ACK就有可能重合, 此时就可以将这两条报文合二为一, 以提高传输效率, 这就是捎带应答的机制. 面向字节流(粘包问题)??粘包问题不仅出现在TCP协议中, 所有面向字节流的机制都可能出现这个问题, 例如文件操作中. ??TCP协议的粘包问题指的是在TCP协议缓冲区中, 多个应用层数据包混在一起. ??发送方发送多条报文之后, 接收方对这些数据进行分用, 分用就意味着将这些数据进行解析, 取出其中的应用层数据, 将其放入接收缓冲区中, 以备接收方的应用程序来取, 然后, 接收方的应用程序就会通过read()方法来从缓冲区中取出数据, 因为TCP协议是面向字节流的, 程序取出的数据就是一些字节, 那么, 从哪个地方到哪个地方的字节是一个完整的数据报呢? ??如果不加处理, 这一问题是无法得到解决的, 处理方式为:在应用层协议中加入包之间的边界, 例如每条数据都以相同的方式结尾, 这样, 就能区分多个数据报. TCP的异常处理
在进程正在运行时突然结束进程, 此时该进程的TCP连接是如何断开的? ??TCP连接是通过socket来建立的, socket本质是进程打开的一个文件, 文件实际上存在于每个进程PCB中的文件描述符表上, 每次打开一个文件(包括socket文件), 都会在文件描述符表中添加一项, 每关闭一个文件就会删除一项. ??如果直接杀死进程, PCB也会直接从PCB表上断开连接并被回收, 里面的文件描述符表也就不存在了, 这些文件相当于自动关闭, 这一过程类似于手动调用socket.close(), 也会触发四次挥手.
??机器正常关机(通过关机键关机)时, 操作系统会终止所有的进程, 每个进程的关闭过程与上述过程相同.
例如,直接关闭电脑的电源, 此时操作系统不会有任何的反应时间, 也不会有处理措施. ??如果是接收方断电, 此时如果客户端还在向接收方发送数据, 就不会收到接收方返回的ACK, 就会触发确认重传机制, 重传依旧会失败, 此时发送方就会认为此次连接出现了严重故障, 就会尝试重新建立连接, 重新建立连接失败之后, 就会放弃进行连接, 并释放相应的连接信息. ??如果是发送方断电, 发送方无法向接收方发送数据, 此时, 接收方无法判断发送方停止发送数据的原因, 就会向发送方发送探测报文, 但始终无法收到探测报文的ACK, 因此判定发送方出现异常, 并且断开此次连接. |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 3:42:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |