传输层:TCP协议解析

news/2024/5/17 18:51:11 标签: TCP

ps:TCP三次握手和四次挥手详解

TCP_1">TCP协议端格式

在这里插入图片描述

  • 16位源端端口、16位目的端端口:描述端与端之间的通信
  • 32位序号、32位确认序号:实现TCP的包序管理,TCP是有序交付的
  • 4位头部长度:以4字节位单位描述TCP报文长度,TCP报头是不定长的,最小20字节,最大60字节
  • 6位标志位:URG、ACK、PSH、RST、SYN、FIN
    URG:紧急标志位
    ACK:确认标志位
    PSH:携带数据标志位
    RST:重置连接标志位
    SYN:连接建立标志位
    FIN:断开连接标志位
  • 16位窗口大小:实现滑动窗口机制,进行流量控制
  • 16位校验和:二进制反码求和算法,校验数据一致性
  • 16位紧急指针:紧急标志位绑定,如果紧急标志位为1,则紧急指针指向的数据有效
  • 0~40字节选项数据:主要用于协商以及描述一些信息

内核当中如果接收到带有URG标志位的请求后,会给当前的应用程序发送SIGURG(23)信号。
如果应用程序特别在乎收到的带有URG标志位的请求:

  1. 更改SIGURG信号的默认处理方式,自定义处理函数
  2. 在自定义处理函数当中调用recv(sock, buf, size, MSG_OOB)

可靠传输

确认应答机制

在这里插入图片描述

  • seq:本条数据的起始序号
  • ack:给对方发送数据的确认序号,告诉对方确认序号之前的数据收到了

三次握手期间,双方会协商起始序号(上图中为了方便演示从0开始,实际中不一定,是一个随机值)。三次握手时,虽然数据长度为0,但是确认序号是对方发送的数据起始序号+1,即 ack = seq + 1。

数据通信期间,确认序号是对方发送数据中的起始序号加上数据长度,即 ack = seq + len。

超时重传机制

在这里插入图片描述
当己方发送一条消息之后,就会开启一个重传计时器,用来计算时间,在RTO时间内如果还没有收到确认应答,则就会重传报文。

  • 重传计时器:timer,作用就是用来计时
  • RTO:超时重传时间,动态计算出来的。RTO = 2 * RTT
  • RTT:报文往返时间。从发送报文开始计算,直到收到确认应答,期间这个时间就是往返时间。
  • 预测下一个要发送数据的 RTT = RTT(prev) * i + (1 - i) * RTT(cur)
    例如:RTT(prev) = 10S,RTT(cur) = 20S
    RTT = 10S * i + 20S * (1 - i)
    iTCP = 0.9 —> 90%
    RTT = 10S * 0.9 + 20S * (1 - 0.9) = 9 + 2 = 11S

滑动窗口机制

额外的丢包问题:

  1. 发送方发送数据过快,接收方来不及处理取出,导致接收缓冲区满溢,则以后的数据都会被丢弃
  2. 发送方发送大量数据, 但是因为网络状态不好导致大量丢包造成重传

解决办法:滑动窗口机制:依靠协议中的窗口大小字段实现流量控制
接收方通过协议中的窗口大小字段告诉发送方,最多可以发送多少数据(窗口大小不超过接收方的接收缓冲区剩余空间总大小)。

MSS:最大数据段大小,表示TCP数据通信时一条数据的最大大小,通信时双方进行协商,取双方MSS中较小的一方作为最大数据段大小。

滑动窗口在发送方维护发送窗口,接收方维护接收窗口,窗口通过一个后沿序号和前沿序号实现。
窗口大小不能超过接收方的接收缓冲区中剩余空间的大小,避免发送的数据太多而导致缓冲区满溢,最后数据被丢弃。

发送窗口:表示一次最多从后沿到前沿发送多少数据,不超过接收方的窗口大小
后沿:所要发送数据的起始序号,后沿的移动取决于是否收到接收方的确认回复
前沿:根据接收方窗口大小计算的结束序号,取决于接收方响应的窗口大小(前沿减去后沿的大小就是接收方的窗口大小)

接收窗口:表示从哪里开始接收数据,接收到多少序号为止,不超过剩余空间大小,进行包序管理,哪个包应该放在缓冲区的什么位置
后沿:接收数据的起始序号,后沿的移动取决于是否收到了后沿的数据
前沿:根据接收缓冲区剩余空间大小计算得到的接收数据的结束序号,前沿的移动取决于缓冲区剩余空间大小
在这里插入图片描述
滑动窗口发送端丢包
如果滑动窗口发送端丢包,则一定需要进行重传。
在这里插入图片描述
滑动窗口接收端丢包
发送端没有收到5号确认包,但是收到了6和7号确认包,意味着接收端一定是收到了5号确认包。
对于发送方而言,如果收到了比丢失确认包序更大的确认包,则不用理会。
在这里插入图片描述
滑动窗口机制中的三种协议:

  • 停等协议:得到一条回复,然后才能发送下一条数据
  • 回退n步协议:一条数据丢失了,则需要发送端将丢失这条数据及以后的数据都进行重传
  • 选择重传协议:一条数据丢失了,则仅仅针对于丢失的这条数据进行重传

拥塞控制机制

如果因为网络状态不好,导致发送的数据丢包越多:拥塞控制
拥塞控制:进行网络探测,以一种慢启动、快增长的传输方式,根据网络状态调整发送速度的机制

慢启动
TCP建立连接之后,一开始不要直接发送大量的数据,而是先发送少量的数据,探测网络的拥塞程度,当网络转发能力好的时候,逐渐扩大拥塞窗口的大小。

慢开始门限:是一个阈值,当拥塞窗口大小小于慢开始门限的时候,执行慢开始算法;否则超过慢开始门限,执行拥塞避免算法。

慢开始算法:对于连接当中每一个轮次的收发数据,拥塞窗口的变化是成指数变化的;慢开始的时候,cwnd(拥塞窗口的大小)是1,当第二个轮次的时候,cwnd是2,当第三个轮次的时候,cwnd是4。

拥塞避免算法:当超过慢开始门限的时候,拥塞窗口的变化是成线性的,每一轮次进行加1。
在这里插入图片描述

  1. 当拥塞窗口大小小于慢开始门限的时候,执行慢开始算法,拥塞窗口大小随着传输轮次,进行指数增长
  2. 当拥塞窗口大小大于慢开始门限的时候,执行拥塞避免算法,拥塞窗口的大小随着传输轮次,进行线性增长
    在这里插入图片描述

快重传
当发送端连续发送多条数据,若接收端接收数据并非是接收后沿数据,则认为有可能后沿数据丢失了,首先不会进行接收到的数据的确认回复,而是向发送端间隔连续发送三次后沿数据的重传请求,要求对方对后沿数据进行重传。若发送方连续收到三条同一重传请求,则对这条数据进行重传。

为什么是三次:避免因为网络延迟、数据报的延迟到达,三次可以有一个缓冲时间,若在第二次的时候收到了后沿数据报,则不再发送第三条重传请求,这时候发送端也就不用重传了。快速重传可以一定程度上避免发送端所必须的超时重传。

快恢复
在这里插入图片描述
如果说网络拥塞导致发送端的某一个TCP报文丢失,接收端会依照快重传,给发送端发送三个重传请求;当发送端能够一连串的收到三个重传请求,针对发送端而言,会认为网络并不是很拥塞,完全没有必要从慢开始进行传输。

  1. 设置新的慢开始门限,慢开始门限 = 拥塞窗口 / 2
  2. 已经废弃的做法:从慢开始进行传输数据,拥塞窗口需要变为1
  3. 如今的做法:
    更改慢开始门限,变成拥塞窗口的一半
    再执行拥塞避免算法

捎带应答机制

当接收端接收到数据之后,进行确认回复,确认回复就是一个报头中的确认序号进行的,为了减少空报头的响应占据带宽,则使用捎带应答,在即将要发送的数据头部中进行上一条接收到的数据的确认回复。
在这里插入图片描述
捎带应答机制减少了网络当中确认包的数量,换句话说,降低了网络拥塞的风险。

延时应答机制

优势:减少网络当中数据包的数量

当接收端接收到数据之后,并不立即进行确认回复(因为如果立即进行确认回复,接收缓冲区剩余空间变小,窗口就变小了,导致传输的吞吐量变小),而是延迟应答,则有可能应答的时候程序在上层已经将数据取出,保证窗口的大小不会变小。
在这里插入图片描述

TCPfont_123">TCP机制总结

可靠传输实现:面向连接、确认应答、超时重传、序号、确认序号、校验和
避免丢包重传:滑动窗口机制、拥塞控制机制
挽救传输性能:快速重传、延迟应答机制、捎带应答机制

面向字节流

字节流传输服务,面向连接的、有序的一种以字节为传输单元的最小传输方式。

发送端在send发送数据的时候,并不会立即封装报头,而是将数据先放到发送缓冲区中,选择合适的时候再去从缓冲区中取出合适大小的数据进行传输。

接收端在recv接收数据的时候,并非一条一条数据向上交付,而是根据recv想要的数据长度从接收缓冲区中取出指定长度的数据进行交付。

优点:传输比较灵活,很多小的数据会集合成一条大的数据进行一次性传输,减少了IO次数,提高了性能(延迟发送可以关闭,可配置的),接收端接收也更加灵活,想要多少取多少。

缺陷:TCP交付的这条数据可能并非是一条完整的数据,也有可能是多条数据(TCP对于上层给与的数据边界不敏感,不关注是几条数据,只关注自己可以传输多少字节的数据,即recv想要多少字节的数据。反之UDP对每条传输的数据有边界区分,每次刚好就只交付一条完整的数据),导致上层将多条数据当作一条数据进行处理了。

TCPfont_139">TCP粘包问题

TCP有可能将多条数据当作一条数据进行处理(UDP是不会出现粘包问题的,因为UDP头部中定义了数据的长度)。

粘包的解决方案:程序员在应用层进行数据的边界管理

  1. 每条数据之间以特殊字符进行间隔
    缺陷:如果数据中有这个特殊字符,就需要进行转义处理
  2. 数据定长传输
    缺陷:数据短小的情况下进行补位,传输了大量的无用数据
  3. 应用层协议头部中定义数据长度:HTTP、UDP
    HTTP:HTTP头部以\r\n\r\n特殊字符间隔表示结束,并且在头部中通过Content-Length确定正文长度
    UDP:在传输层就进行了粘包的解决,头部定长8字节,头部中定义数据长度

如:实现带有定长包头和包尾的应用层数据
定长包头:当前的数据包大小
包尾:区分每一条数据的边界位置,常见的包尾 \r\n(0D 0A)
在这里插入图片描述
\r\n 常见在应用层协议当中,作为分隔符存在,二进制表示是 0D 0A,使用分隔符其实是增加数据边界的功能。

先按照分隔符(\r\n)来进行定位:上一条数据\r\n下一条数据【4个字节的头部(数据长度)】【真实的数据内容】
从下一条数据的包头解析数据长度,进而根据长度去处理真实的数据内容

应用层如何处理半条数据?

  1. 数据剩下一个尾部,从接收缓冲区中接收回来。需要找到第一个分隔符,分隔符的前半部分就是上一次从接收缓冲区当中接受数据剩下的后半部分,将这一次的后半部分和上一次的前半部分组合起来,就是完整的一个数据。
  2. 只接收了前半部分数据,应用层将未完整的前半部分数据先缓存起来。

http://www.niftyadmin.cn/n/1617625.html

相关文章

python-公式求值

公式求值(10分) 题目内容: 接受一个正整数输入x,打印上述公式的输出值。 输入格式: 共一行,为一个正整数。 输出格式: 共一行,采用round函数保留10位小数。 输入样例: 1 输出样例…

传输层:UDP协议解析

UDP协议端格式 16位源端端口、16位目的端端口:描述端与端之间的通信16位UDP长度:表示整个数据报(UDP首部UDP数据)的最大长度,限制了UDP报文总长度(包含报头在内)不能超过64K16位校验和:使用二进制反码求和算…

python-特殊的数

特殊的数(10分) 题目内容: 一个特殊的正整数,它加上150后是一个完全平方数,再加上136又是一个完全平方数,求符合条件的最小的一个数。 输入格式: 无需输入 输出格式: 共一行,为一…

socket网络编程:UDP通信、TCP通信

本篇文章默认你对UDP协议和TCP协议已经理解掌握了:UDP协议详解、TCP协议详解 UDP网络通信编程 首先我们需要知道 UDP协议是传输层协议,面向数据报,无连接,不可靠传输,实时性高。 创建套接字:使进程与网…

python-大大的叉

大大的叉&#xff08;10分&#xff09; 题目内容&#xff1a; 打印出n阶的“叉”&#xff0c;这个叉图案由字符‘’和‘X’构成&#xff0c;n越大&#xff0c;这个图案也就越大 输入格式: 一个正整数n&#xff0c;1<n<20 输出格式&#xff1a; 一个n阶叉图案 输入样例…

应用层:HTTP协议解析

HTTP协议是超文本传输协议&#xff0c;规定了客户端&#xff08;浏览器&#xff09;和服务端之间的通信格式。 特点 基于请求响应模型默认端口&#xff1a;80无状态的&#xff0c;底层是TCP实现&#xff0c;所以是可靠的 基于请求响应模型就是指每一次业务过程都是客户端请求…

python-约瑟夫环问题

约瑟夫环问题&#xff08;10分&#xff09; 题目内容&#xff1a; 已知n个人&#xff08;以编号0&#xff0c;1&#xff0c;2&#xff0c;3...n-1分别表示&#xff09;围坐在一张圆桌周围。从编号为0的人开始报数1&#xff0c;数到m的那个人出列&#xff1b;他的下一个人又从…

HTTPS加密过程解析

在学习本篇文章之前&#xff0c;我默认你已经熟悉掌握&#xff1a;HTTP协议解析 在HTTP通信过程中&#xff0c;当我们使用Fiddler进行抓包&#xff0c;会发现我们在网页上输入的数据直接就是明文&#xff0c;我们的密码或者任何隐私的东西&#xff0c;都是"裸奔"在互…