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

目录

一、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.mzph.cn/news/707966.shtml

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

相关文章

大数据分布式计算工具Spark实战讲解(数据输入实战)

Python数据容器转RDD对象 PySpark支持通过SparkContext对象的parallelize成员方法,将: - list - tuple - set - dict - str 转换为PySpark的RDD对象 注意: •字符串会被拆分出1个个的字符,存入RDD对象 •字典仅有key会被存入…

Open Harmony开发之分布式账本

简介 Demo基于Open Harmony系统使用ETS语言进行编写,本Demo主要通过设备认证、分布式拉起、分布式数据管理等功能来实现。 应用效果 设备认证,获取同一个局域网内的设备ID,并拉起应用 添加数据并在另一台设备显示该数据 开发步骤 1.新建Openharmony…

安卓使用okhttpfinal下载文件,附带线程池下载使用

1.导入okhttp包 implementation cn.finalteam:okhttpfinal:2.0.7 2.单个下载 package com.example.downloading;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.util.Log; import android.view.View;import java.io.File;import c…

大数据分布式计算工具Spark数据计算实战讲解(map方法,flatmap方法,reducebykey方法)

数据计算 map方法 PySpark的数据计算,都是基于RDD对象来进行的,那么如何进行呢? 自然是依赖,RDD对象内置丰富的:成员方法(算子) 功能:map算子,是将rdd的数据一条条处…

Java 小项目开发日记 01(注册接口的开发)

Java 小项目开发日记 01&#xff08;注册接口的开发&#xff09; 1.项目需求 完成注册接口 2.项目目录 3. 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

NWatch-Alarm闹钟功能实现

文章目录 W25Q64初始化SPI初始化W25Q初始化 AlARM模块初始化AlARM模块绘制Draw函数AlARM的更新函数AlARM中最重要的函数 W25Q64初始化 W25Q64用来存储用户设置的闹钟值&#xff0c;开机的时候自动读取闹钟记录。 SPI初始化 使用CubeMx自动配置。 #define SPI1CS_ON HAL_GP…

3d模型导出简单线条的步骤---模大狮模型网

导出简单线条的3D模型通常涉及以下步骤&#xff1a; 创建线条模型&#xff1a;首先&#xff0c;在您的3D建模软件中创建或导入包含线条的模型。这可以是简单的线框模型&#xff0c;也可以是由线条构成的复杂形状。确保您的模型中只包含您希望导出的线条部分。 选择导出格式&am…

Python的自然语言处理库NLTK介绍

NLTK&#xff08;Natural Language Toolkit&#xff09;简介 NLTK是Python中一个领先的自然语言处理&#xff08;NLP&#xff09;库&#xff0c;它提供了文本处理的基础设施&#xff0c;包括分词&#xff08;tokenization&#xff09;、词性标注&#xff08;part-of-speech tag…

yolov5v7v8目标检测增加计数功能--免费源码

在yolo系列中&#xff0c;很多网友都反馈过想要在目标检测的图片上&#xff0c;显示计数功能。其实官方已经实现了这个功能&#xff0c;只不过没有把相关的参数写到图片上。所以微智启软件工作室出一篇教程&#xff0c;教大家如何把计数的参数打印到图片上。 一、yolov5目标检测…

前端Ajax获取当前外网IP地址并通过腾讯接口解析地理位置

目录 一、获取访问端IP地址 二、可用的IP获取接口 1、韩小韩IP获取接口&#xff1a; 2、ipify API 附3、失败的太平洋接口 三、腾讯位置服务-IP位置查询接口 一、获取访问端IP地址 原计划使用后端HttpServletRequest 获取访问端的IP地址&#xff0c;但在nginx和堡垒机等阻…

峟思科普小(1)型土石坝安全监测设备的基本配置与策略

土石坝&#xff0c;作为水利工程中的重要组成部分&#xff0c;其安全性能直接关系到下游人民的生命财产安全。为了确保土石坝的安全运行&#xff0c;必须对其进行科学有效的安全监测。本文将详细阐述小(1)型土石坝安全监测设备的基本配置与策略。 首先&#xff0c;对于存在渗漏…

JVM运行时数据区——运行时数据区及线程概述

文章目录 1、运行时数据区概述2、线程3、小结 内存是非常重要的系统资源&#xff0c;是硬盘和CPU的中间仓库及桥梁&#xff0c;承载着操作系统和应用程序的实时运行。JVM在程序执行期间把它所管理的内存分为若干个不同的数据区域。这些不同的数据区域可以分为两种类型&#xff…

“智农”-农业一体化管控平台

大棚可视化|设施农业可视化|农业元宇宙|农业数字孪生|大棚物联网|大棚数字孪生|农业一体化管控平台|智慧农业可视化|智农|农业物联网可视化|农业物联网数字孪生|智慧农业|大棚三维可视化|智慧大棚可视化|智慧大棚|农业智慧园区|数字农业|数字大棚|农业大脑|智慧牧业数字孪生|智…

【饮食】如何有效的补充维生素,矿物质?学习笔记(附膳食营养素参考摄入量DRIs)

程序员养生指南之 【饮食】如何有效的补充维生素&#xff0c;矿物质&#xff1f;学习笔记&#xff08;附膳食营养素参考摄入量DRIs&#xff09; 文章目录 一、维生素补充1、需要补充维生素的情况2、食补&#xff1a;缺啥补啥3、补充剂&#xff08;无脑吃&#xff09; 二、膳食营…

Android 跨进程通信aidl及binder机制详解(一)

前言 上文中描述了&#xff0c;什么是绑定服务、以及创建一个绑定服务都可以通过哪些方式&#xff0c;同时说了通过扩展Binder类来创建一个绑定服务&#xff0c;并使用一个例子来说明了客户端与服务端的绑定过程&#xff0c;最后又总结了绑定服务的生命周期与调用过程。由于上…

(unity学习)一些效果的学习

一、学习视频 【Unity教程】零基础带你从小白到超神 二、效果实现 三、问题解决 Unity 点击UI与点击屏幕冲突的解决方案 关于unity UI界面操作与场景内操作不冲突问题

Unity安装与简单设置

安装网址&#xff1a;https://unity.cn 设置语言&#xff1a; 设置安装位置&#xff1a;否则C盘就会爆了 获取一个个人的资格证&#xff1a; 开始安装&#xff1a; 安装完毕。 添加模块&#xff1a;例如简体中文 新建项目&#xff1a; 布局2*3、单栏布局、 设置…

4. client-go 编程式交互

Kubernetes 系统使用 client-go 作为 Go 语言的官方编程式交互客户端库&#xff0c;提供对 Kubernetes API Server 服务的交互访问。Kubernetes 的源码中已经集成了 client-go 的源码&#xff0c;无须单独下载。client-go 源码路径为 vendor/k8s.io/client-go。 开发者经常使用…

前端架构: 脚手架之包管理工具的案例对比及workspace特性的基本使用

Npm WorkSpace 特性 1 &#xff09;使用或不使用包管理工具的对比 vue-cli 这个脚手架使用 Lerna 管理&#xff0c;它的项目显得非常清晰在 vue-cli 中包含很多 package 点开进去&#xff0c;每一个包都有package.json它里面有很多项目&#xff0c;再没有 Lerna 之前去维护和管…

threehit二次注入案例

君衍. 一、环境搭建1、conn.php源码&#xff1a;2、register.php源码3、login.php源码4、index.php源码5、demo.php源码 二、数据库环境搭建1、注意点一2、注意点二报错原因 三、复现过程1、user12、user23、user34、user45、user56、user6-name7、user7-table8、user8-column9…