Linux网络编程(四-TCP协议)

news2025/2/24 8:34:18

目录

一、TCP概念

二、TCP的首部格式

三、TCP可靠传输机制

3.1 确认应答机制

3.2 超时重传机制 

3.3 连接管理 

3.3.1 三次握手

3.3.2 四次挥手

3.4 流量控制 

3.5 拥塞控制

四、TCP效率机制

4.1 滑动窗口 

4.2 重发控制 

4.3 延迟应答 

4.4 捎带应答

五、TCP的异常情况处理 

六、TCP协议特点总结


一、TCP概念

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接(连接导向)的、可靠的、 基于IP的传输层协议。TCP协议属于OSI七层模型中的传输层

二、TCP的首部格式

TCP协议段分为首部用户数据部分,TCP协议段结构如图所示:

TCP首部不包括选项为固定20字节

  • 源端口号:表示发送端端口号,字段长16位。
  • 目的端口号:表示接收端端口号,字段长16位。
  • 序号:表示发送数据的位置,每发送一次数据,就累加一次该数据字节数的大小。注意:序号不会从0或1开始,而是在建立连接时由计算机生成的随机数作为其初始值,通过SYN包传给接收端主机。然后再将每转发过去的字节数累加到初始值上表示数据的位置。此外,在建立连接和断开连接时发送的SYN包和FIN包虽然并不携带数据,但是也会作为一个字节增加对应的序号,字段长32位。
  • 确认序号:用于给对方的响应,值为收到TCP报文段的序号值加1(表示当前的应答报文针对的是哪个消息进行的确认应答),发送端收到这个确认序号以后可以认为在这个序号之前的所有数据都已经被正常接收,字段长32位。
  • 4位首部长度:表示TCP首部的长度,字段长4位,单位为4字节,所以该字段能表示的长度范围为[0,60]字节,而不包括选项的首部长度固定为20字节,所以该字段真实的取值范围为[5,15] × 4字节为[20,60]字节,二进制表示为[0101,1111]。
  • 6个标志位:
    • URG:紧急标志位,配合16为紧急指针使用。
    • ACK:确认应答标志位,凡是报文具有应答特性,该标志位就会被设置为1。
    • PSH:用于提示接收端应用程序立刻从TCP缓冲区将数据取走。
    • RST:用于重新建立连接,RST为1时,TCP必须强制断开连接,在重新建立连接。
    • SYN:用于建立连接,SYN为1时,表示希望建立连接。
    • FIN:用于断开连接,FIN为1时,表示今后不会再有数据发送,希望断开连接。
  • 窗口大小:进行流量窗口控制,字段长16位。
  • 校验和:发送端填充,CRC校验,接收端校验不通过,则认为数据有问题,此处的检验和不光包含TCP首部,也包含TCP数据部分,字段长16位。
  • 紧急指针:标识那部分数据时紧急数据,字段长16位。

三、TCP可靠传输机制

3.1 确认应答机制

在TCP中,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知,这个消息叫做确认应答(ACK)。 

TCP通过确认应答(ACK)机制实现可靠的数据传输,当发送端将数据发出之后会等待对端的确认应答,如果有确认应答则说明数据已经成功达到对端,反之,则数据大概率丢失。 

TCP将每个字节的数据都进行了编号,即为序列号(序号)

每一个确认应答(ACK)都带有对应的确认序列号,意思告诉发送者,我已经收到哪些数据,下一次你从哪里开始发送。 

3.2 超时重传机制 

发送端在一定时间内没有收到确认应答,发送端就认为数据已经丢失,并进行重发。由此,即使产生了丢失,仍然能够保证数据能够到达对端,实现可靠传输,这就是超时重传机制

主机A发送数据给主机B之后,可能因为网络拥堵等原因导致数据丢失无法到达主机B。此时,如果主机A在一个特定的时间间隔内都未收到主机B发来的确认应答(ACK),则会将该数据进行重发。

未收到确认应答并不意味着数据一定丢失,也有可能是确认应答(ACK)丢失,这种情况也会导致发送端因没有收到确认应答(ACK)而进行重发。上图中,主机A因未收到主机B的确认应答(ACK),而对数据进行了重发,主机B其实已经收到了两次1~1000的数据,再收到第二次1~1000的数据时,主机B会根据序列号来进行去重。(接收的数据会放在操作系统内核的接收缓冲区中,接收缓冲区可以视为是一个阻塞队列,对于收到的数据,TCP会根据序号检查这个数据是不是在缓冲区中已经存在,如果存在则丢弃,如果不存在则放进去)

3.3 连接管理 

在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。 

3.3.1 三次握手

过程:

  1. 客户端向服务器端发送连接请求(SYN),申请建立客户端到服务器端的连接。
  2. 服务器端返回确认应答(ACK)(第一次SYN的应答)和连接请求(SYN),申请建立服务器端到客户端的连接。
  3. 客户端收到数据,状态置为ESTABLISHED,表示客户端到服务器端连接建立完成,并且发送确认应答(ACK)(第二次SYN的应答),服务器端收到数据,状态置为ESTABLISHED,表示服务器端到客户端的连接建立完成。

服务器端状态转化:

  • [CLOSED -> LISTEN]:服务器端调用listen函数后进入监听状态,等待客户端连接。
  • [LISTEN -> SYN_RCVD]:一旦监听到连接请求(SYN),就将该连接放入内核等待队列中,并向客户端发送ACK+SYN,应答并请求建立连接。
  • [SYN_RCVD -> ESTABLISHED]:服务器端一旦收到客户端的确认应答(ACK),就进入ESTABLISHED状态,表示连接建立完成,可以进行数据传输。

客户端状态转化:

  • [CLOSE -> SYN_SENT]:客户端调用connet函数,向服务器端发起连接请求(SYN)。
  • [SYN_SENT -> ESTABLISHED]:收到服务器端的确认应答(ACK),connect函数调用成功,进入ESTABLISHED状态,表示连接建立完成,可以进行数据传输。
3.3.2 四次挥手

过程:

  1. 客户端发送FIN到服务器端,申请关闭客户端到服务器端的连接。
  2. 服务器端收到FIN状态置为CLOSE_WAIT,并返回确认应答(ACK)。(这个动作是系统实现TCP协议栈默认执行的,不需要程序来调用代码)
  3. 服务器端发送FIN到客户端,申请关闭服务端到客户端的连接。(程序手动调用close函数)
  4. 客户端收到FIN返回确认应答(ACK),并进入TIME_WAIT时间等待状态,客户端等待一段时间后,状态置为CLOSED,表示已经关闭连接。服务器端收到确认应答(ACK)后,状态置为CLOSED,表示已经关闭连接。

服务器端状态转化:

  • [ESTABLISHED -> CLOSE_WAIT]:当客户端主动关闭连接(调用close),服务器端会收到结束报文段(FIN),服务器返回确认应答(ACK),进入CLOSE_WAIT状态。
  • [CLOSE_WAIT -> LAST_ACK]:进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据)。当服务器端真正调用close关闭连接时,会向客户端发送FIN,此时服务器进入LAST_ACK状态,等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)。
  • [LAST_ACK -> CLOSE]:服务器端收到FIN的确认应答(ACK),进入CLOSE状态,彻底关闭连接。

客户端状态转化:

  • [ESTABLISHED -> FIN_WAIT_1]:客户端主动调用close时, 向服务器端发送结束报文段(FIN), 同时进入FIN_WAIT_1;
  • [FIN_WAIT_1 -> FIN_WAIT_2]:客户端收到服务器对结束报文段的确认应答(ACK), 则进入FIN_WAIT_2,开始等待服务器的结束报文段(FIN)。
  • [FIN_WAIT_2 -> TIME_WAIT]:客户端收到服务器发来的结束报文段(FIN), 进入TIME_WAIT状态,向服务器端发送结束报文段(FIN)的确认应答(ACK)。
  • [TIME_WAIT -> CLOSED]:客户端要等待一个2MSL(Max Segment Life,报文最大生存时间)的时间,才会进入CLOSED状态,此时彻底关闭连接。

常见问题: 

  • 为什么服务端不将ACK和FIN合并一起发送,形成三次挥手呢?

答:ACK和FIN的发送时机不同,ACK是操作系统内核响应的(立即执行),FIN是需要由用户程序调用close函数才会发送,用户调用close函数的时间和内核响应的时间不同。

  • 为什么客户端要等待一段时间状态才置为CLOSED,而不直接将状态置为CLOSED?

答:如果客户端发给服务器端最后一个确认应答(ACK)丢失,此时,服务器端会重新给客户端发送结束报文段(FIN),如果直接置为CLOSE状态,则接收不到客户端重新发送结束报文段(FIN),从而导致无法重发确认应答(ACK),使服务器端无法进入CLOSED状态。

3.4 流量控制 

接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制(Flow Control)

  • 接收端将自己剩余缓冲区大小存入TCP协议段首部中的“16位窗口大小”字段 ,通过确认应答(ACK)通知发送端,窗口大小越大,说明接收端的接收能力越强。
  • 发送端根据接收到这个窗口的大小,控制自己的发送速度。
  • 如果接收缓冲区满了,就会将窗口大小设置为0,这时,发送端不再发送数据,而是定期的发送一个窗口探测报文(只是为了知道窗口的大小),让接收端将窗口大小告诉发送端。

3.5 拥塞控制

TCP通过滑动窗口能够高效可靠的发送大量的数据,但是如果在刚开始阶段就发送大量的数据,可能会引发其他问题,一般来说,计算机网络都处在一个共享的环境,在网络出现拥堵时,突然发送一个较大量的数据,极有可能导致整个网络的瘫痪。 

TCP为了防止该问题的出现,引入慢启动机制,对发送数据量进行控制。 这里引入拥塞窗口,刚开始时,拥塞窗口设置为1,每收到一个确认应答(ACK)时,拥塞窗口加1,每次发送数据的时候,拥塞窗口和流量窗口的较小的值作为实际发送的窗口,即滑动窗口的大小。

拥塞窗口的增长速度是指数级别的,增长速度非常的快,为了控制增长速度,引入了一个叫做慢启动的阈值,当拥塞窗口超过这个阈值时,不再按照指数方式增长,而变为线性增长。

  • 当TCP开始启动的时候, 慢启动阈值等于窗口最大值。
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1。

四、TCP效率机制

4.1 滑动窗口 

由于TCP的确认应答机制存在,导致对每一个发送的数据段都要返回确认应答(ACK),收到确认应答(ACK)后,再发送下一个数据段,这样的传输方式产生了一个缺点,那就是,数据往返时间越长通信性能就越低。 

           

为解决这个问题,TCP引入了窗口这个概念,即使再往返时间较长的情况下,它也能够控制网络性能的下降,如上图所示,确认应答不再是单个数据段进行应答,而是以多个数据段进行应答,这个多个数据段的值由窗口大小控制,图中的窗口大小为4000个字节(四个数据段),发送前四个数据段的时候,不需要等待任何确认应答(ACK),直接发送。 

 

滑动窗口存在于发送端的发送缓冲区中,属于发送端的发送缓冲区的一部分

  • 滑动窗口中的数据段因其某种原因已在传输中丢失,发送端未收到此数据段的确认应答(ACK),此时滑动窗口保持不变,滑动窗口中数据段进行超时重传。
  • 滑动窗口以外的左边是已发送且收到应答的数据,右边是尚未发送的数据。
  • 滑动窗口中的数据段发送后,若如期收到确认应答(ACK),滑动窗口将会滑动到确认应答(ACK)中的序列号的位置,原先的数据段就可以不用进行重发,此时数据段就可以从滑动窗口中清除,滑动窗口整体向右滑动。
  • 滑动窗口的大小为min(流量窗口的大小,拥塞窗口的大小)

  • 滑动窗口本质为:指针或数组下标(暂且认为),int win_start、int win_end
  • 滑动窗口可以为0吗?答:可以,win_end由确认应答(ACK)中的16为窗口大小决定,当接收缓冲区慢的时候,窗口大小就会被设置为0,此时滑动窗口大小就为0。
  • 如果没有收到开始的报文的确认应答,而收到中间的影响吗?答:不影响
  • 滑动窗口如果一直向右移动会越界吗?答:不会,发送缓冲区为环形

4.2 重发控制 

滑动窗口传输数据过程中出现丢包,如何进行重传?

情况一:数据包已经抵达,确认应答(ACK)丢失 

这种情况下,不是确认应答(ACK)丢失不要紧,可以通过后续的确认应答(ACK)进行确认,确认应答(ACK)中确认序号的含义为确认序号前的所有序号都已经全部收到。 

情况二:数据包丢了 

  • 当1001~2000这段报文丢失后,发送端一直会收到1001这样的确认应答(ACK)。
  • 如果发送端主机连续三次收到相同的确认应答(ACK)如1001应答,那发送端主机就会重新发送1001~2000数据,此时,接收端收到1001~2000数据后,再次返回的确认应答(ACK)就是7001了,因为2001~7000数据都已经接收到了,被放到接收端操作系统内核的接收缓冲区中。

这种机制,即时不超时也会发生重传,称作“ 高速重发控制 ”也叫“ 快重传机制 ”。 

4.3 延迟应答 

接收数据的主机如果每次都立刻回复确认应答(ACK)的话,可能会返回一个较小的流量窗口,但是流量窗口越大,网络吞吐量越大,传输效率就越高,所以等待一部分时间,待接收端处理完一部分数据 ,就可以将流量窗口设置为大一点的值,这样网咯吞吐量大,效率高。

延迟是为了高吞吐量,但是也不能无限延迟,

  • 数量限制,每隔n个包就应答一次
  • 时间限制,超过最大延迟时间,就应答一次

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

4.4 捎带应答

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 "一发一收" 的,这意味着,TCP的确认应答(ACK)和回执数据可以通过一个包发送,这种方法就是捎带应答,通过这种机制可以使收发的数据量减少。需要注意:捎带应答需要依赖延迟应答

五、TCP的异常情况处理 

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

六、TCP协议特点总结

  • 有连接:通过三次握手建立连接后才可接发数据。
  • 可靠传输:网络数据传输是一跳一跳的,经过路途中的设备可能发生数据丢失,可靠传输是可能发生数据丢失但有机制保证对方能接收到。
  • 面向字节流:可以多次的收发数据(连接没有关闭时,可以多次的接收和发送数据)
  • 有接收缓冲区和发送缓冲区:发送数据时,是先写到发送缓冲区,再刷新缓冲区(flush)
  • 大小不受限制:多次的收发数据,每次的数据可以很大

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1477955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux C | 网络编程】gethostbyname 函数详解及C语言例子

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

【Java程序设计】【C00323】基于Springboot的高校科研信息管理系统(有论文)

基于Springboot的高校科研信息管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的高校科研信息管理系统,本系统有管理员、学校管理员、科研人员三种角色; 管理员:首页、个…

企业数字化转型的第一步:由被动多云向主动多云转变

随着经济环境、市场形势、技术发展、用户需求等诸多因素的变化,数字化转型为企业进一步提升效率和竞争力、提供更加丰富的个性化产品和服务、进行业务场景创新、探寻新的增长机会和运营模式提供了崭新的途径。越来越多的企业意识到,数字化转型已不是企业…

数据仓库与数据挖掘概述

目录 一、数据仓库概述 (一)从传统数据库到数据仓库 (二)数据仓库的4个特征 (三)数据仓库系统 (四)数据仓库系统体系结构 (五)数据仓库数据的粒度与组织…

机器人内部传感器阅读梳理及心得-速度传感器-数字式速度传感器

在机器人控制系统中,增量式编码器既可以作为位置传感器测量关节相对位置,又可作为速度传感器测量关节速度。当作为速度传感器时,既可以在模拟量方式下使用,又可以在数字量方式下使用。 模拟式方法 在这种方式下,需要…

day02_前后端环境搭建(前端工程搭建,登录功能说明,后端项目搭建)

文章目录 1. 软件开发介绍1.1 软件开发流程1.2 角色分工1.3 软件环境1.4 系统的分类 2. 尚品甄选项目介绍2.1 电商基本概念2.1.1 电商简介2.1.2 电商模式B2BB2CB2B2CC2BC2CO2O 2.2 业务功能介绍2.3 系统架构介绍2.4 前后端分离开发 3. 前端工程搭建3.1 Element-Admin简介3.2 El…

django框架不调试下会被达出史(sql查询次数,消耗时间)

1:使用pycharm编辑器里面 2:安装django-debug-toolbar 3:进行调试查询 https django框架调试,各个面板查询消耗时间,pycharm,debug 1:settings.py INSTALLED_APPS列表中添加 INSTALLED_APPS [# 使用多合一有点慢# multi_captcha_admin,# 多合一验证码i…

Git安装的一些步骤解说(小白好奇心严重版本)

Use bundled OpenSSH 安装 Git 时,您面临的选择是使用 Git 自带的 SSH 客户端(bundled OpenSSH)还是使用系统上已安装的外部 SSH 客户端(external OpenSSH)。以下是两个选项的一些考虑因素: 使用 Git 自带的…

2/29作业

typedef int datatype; typedef struct link_list { union { int len; datatype data; }; struct link_list *next; }link_list,*link_p; #include "link_list.h" int main(int argc,const char *argv[]) { //创建链表并填入数据 …

阿里云服务器大降价20%,简单拥有五年三台2h4gECS,组建公网集群

要在阿里云ECS上组建集群,您可以按照以下步骤进行操作: 创建ECS实例:登录阿里云控制台,选择ECS实例,点击“创建实例”按钮。根据实际需求选择实例的配置参数,例如实例规格、操作系统、网络等。根据需要选择…

Spring Boot Profiles简单介绍

Spring Boot application.properties和application.yml文件的配置 阅读本文之前,请先阅读上面的配置文件介绍。 Spring Boot Profiles是一个用于区分不同环境下配置的强大功能。以下是如何在Spring Boot应用程序中使用Profiles的详细步骤和代码示例。 1. 创…

buuctf_web_loveSQL

题目: 上面有行小红字,“用 sqlmap 是没有灵魂的”,呵呵。。嗯,确实 啥也憋说,先上万能钥匙: a or 11 # a’ or 11 # a" or 11 # 尝试后的结果,可以发现该SQL验证是单引号,a or 11 #注入过…

预训练大模型LLM的PEFT之—— Prefix Tuning

简介 Prefix Tuning是2021.01提出来的,在它之前,我们使用prompt主要是人工设计模板或者自动化搜索模板,也就是prompt范式的第一阶段,就是在输入上加上prompt文本,再对输出进行映射。这种离散模板对模型的鲁棒性很差。…

【YOLO v5 v7 v8 小目标改进】RFB:组合不同大小的卷积核和扩张卷积来模拟人类视觉感受野的多尺度特性

RFB:组合不同大小的卷积核和扩张卷积来模拟人类视觉感受野的多尺度特性 提出背景RFB 原理空间感受野结构RFB-Net 小目标涨点YOLO v5 魔改YOLO v7 魔改YOLO v8 魔改 提出背景 当前表现最好的目标检测器依赖于深层CNN骨干网络,如ResNet-101和Inception&am…

qt5与qt6的cmake区别

文章目录 使用cmake构建qt项目,坑很多。一是本身就麻烦,二是,确实坑,因为不同的qtcreator版本,选了不同的kits(套件) 生成的CMakeList.txt文件也不一样。 如果可以的话都选择Qt6的相关选项&…

【C++】认识类和对象

🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 一、什么是面向对象?二、类的引入三、类的定义四、类的访问限定符与…

一文速览深度伪造检测(Detection of Deepfakes):未来技术的守门人

一文速览深度伪造检测(Detection of Deepfakes):未来技术的守门人 前言一、Deepfakes技术原理卷积神经网络(CNN):细致的艺术学徒生成对抗网络(GAN):画家与评审的双重角色…

异常网络下TCP的可靠服务机制(慢启动、拥塞避免、快重传、快恢复)

目录 TCP超时重传拥塞控制概述慢启动和拥塞避免下面讲解发送端如何判断拥塞发生。 快速重传和快速恢复 本文描述TCP在异常网络下的处理方式 以保证其可靠的数据传输的服务 TCP超时重传 tcp服务能够重传其超时时间内没有收到确认的TCP报文段,tcp模块为每一个报文段都…

【机器学习】特征选择之包裹式特征选择法

🎈个人主页:豌豆射手^ 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:机器学习 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进…

matlab实现不同窗滤波器示例

1 汉明窗低通滤波器 : 在Matlab中使用汉明窗设计低通滤波器可以通过fir1函数实现。汉明窗通常用于设计滤波器,可以提供更突出的频率特性。 下面是一个示例代码,演示如何在Matlab中使用汉明窗设计低通滤波器: % 定义滤波器参数 fs …