LWIP_TCP 协议

news2025/1/20 11:01:03

目录

1 TCP 协议简介

1.1 TCP 协议简介

1.2 TCP 的建立连接

1.3 TCP 终止连接

1.4 TCP 报文结构

 1.5 lwIP 的 TCP 报文首部数据结构

1.6 lwIP 的 TCP 连接状态图

 


1 TCP 协议简介

1.1 TCP 协议简介

        TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

        TCP 为了保证数据包传输的可靠行,会给每个包一个序号,同时此序号也保证了发送到接收端主机能够按序接收。然后接收端主机对成功接收到的数据包发回一个相应的确认字符( ACK, Acknowledgement),如果发送端主机在合理的往返时延( RTT) 内未收到确认字符ACK,那么对应的数据包就被认为丢失并将被重传。 TCP 协议,它是基于连接的一种传输层协议,在发送数据之前要求系统需要在不可靠的信道上建立可靠连接,我们称之为“三次握手”。 建立连接完成之后客户端与服务器才能互发数据, 不需要发送数据时,可以断开连接,这里我们称之为“四次挥手”。

1.2 TCP 的建立连接

        握手之前主动打开连接的客户端结束 CLOSED 阶段,被动打开的服务器端也结束CLOSED 阶段,并进入 LISTEN 阶段。随后开始“三次握手”:

① TCP 服务器进程先创建传输控制块 TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了 LISTEN(监听)状态。

② TCP 客户进程也是先创建传输控制块 TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位 SYN=1,同时选择一个初始序列号 seq=x ,此时, TCP 客户端进程进入了SYN-SENT(同步已发送状态)状态。 TCP 规定, SYN 报文段(SYN=1 的报文段)不能携带数据,但需要消耗掉一个序号。

③ TCP 服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该ACK=1, SYN=1,确认号是 ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时, TCP服务器进程进入了 SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。

④ TCP 客户进程收到确认后,还要向服务器给出确认。确认报文的 ACK=1, ack=y+1,自己的序列号 seq=x+1,此时, TCP 连接建立,客户端进入 ESTABLISHED(已建立连接)状态。 TCP 规定, ACK 报文段可以携带数据,但是如果不携带数据则不消耗序号。

当服务器收到客户端的确认后也进入 ESTABLISHED 状态,此后双方就可以开始通信了。这就是“三次握手”的过程,如下图所示。

1.3 TCP 终止连接

        建立一个连接需要三次握手而终止一个连接需要四次挥手,终止连接有以下过程。

(1) 第一次挥手:客户端发送释放报文,并停止发送数据。释放数据报文首部, FIN=1,其序列号为 seq=u,此时,客户端进入 FIN-WAIT1(等待服务器应答 FIN 报文)。

(2) 第二次挥手:服务器收到客户端的 FIN 报文后,发出确认报文 ACK=1、 ack=u+1,并携带自己的序列号 seq=v。此时,服务器进入 CLOSE-WAIT(关闭等待) 状态。客户端收到服务端确认请求,此时,客户端进入 FIN-WAIT2(终止等待 2)状态,等待服务器发送连接释放报文。

(3) 第三次挥手:服务器向客户端发送连接释放报文 FIN=1、 ack=u+1,此时,服务器进入了 LAST-ACK(最后确认)等待客户端的确认。客户端接收到服务器的连接释放报文后,必须发送确认 ack=1、 ack=w+1,客户端的序列号为 seq=u+1,此时,客户端进入 TIME-WAIT(时间等待)。

(4) 第四次挥手:服务器接收到客户端的确认报文,立刻进入 CLOSED 状态。

这四次挥手就是终止 TCP 协议连接,如下图所示:

1.4 TCP 报文结构

        在传输层中, TCP 的数据包称为数据段, TCP 报文段与 UDP 报文段一样都是封装在 IP 数据报中发送。 TCP 首部包含建立与断开、数据确认、窗口大小通告、数据发送相关的所有标志和控制信息, TCP 报文结构如下图所示:

(1) 源、目标端口号字段:占 16 比特。 TCP 协议通过使用”端口”来标识源端和目标端的应用进程。端口号可以使用 0 到 65535 之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在”众所周知的端口”( Well-Know Port)为用户提供服务。

(2) 序列号字段:占 32 比特。用来标识从 TCP 源端向 TCP 目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。

(3) 确认号字段:占 32 比特。只有 ACK 标志为 1 时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节。

(4) 头部长度字段:占 4 比特。给出头部占 32 比特的数目。没有任何选项字段的 TCP 头部长度为 20 字节;最多可以有 60 字节的 TCP 头部。

(5) 标志位字段(U、 A、 P、 R、 S、 F):占 6 比特。各比特的含义如下:

① URG: 紧急指针有效。

② ACK: 为 1 时,确认序号有效。

③ PSH: 为 1 时,接收方应该尽快将这个报文段交给应用层。

④ RST: 为 1 时,重建连接。

⑤ SYN: 为 1 时,同步程序,发起一个连接。

⑥ FIN: 为 1 时,发送端完成任务,释放一个连接。

(6) 窗口大小字段:占 16 比特。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。

(7) TCP 校验和字段:占 16 比特。对整个 TCP 报文段,即 TCP 头部和 TCP 数据进行校验和计算,并由目标端进行验证。

(8) 紧急指针字段:占 16 比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。

(9) 选项字段:占 32 比特。可能包括”窗口扩大因子”、”时间戳”等选项。

上述的内容讲解的是 TCP 首部信息,这些信息被封装在一个 IP 数据报中, 该数据报结构如下图所示。

 1.5 lwIP 的 TCP 报文首部数据结构

        实现 TCP 协议的文件有 tcp.h、 tcp.c、 tcp_in.c 和 tcp_out.c,这四个文件实现了 TCP 协议全部数据结构和函数, 其中 tcp.c 文件包含了与 TCP 编程、 TCP 定时器相关的函数,而tcp_in.c 文件包含了 TCP 报文段输入处理函数, 而 tcp_out.c 文件包含了 TCP 报文输出处理函数, 当然 tcp.h 定义了宏和结构体。 首先我们看一下 TCP 首部结构,这个结构为 tcp_hdr, 如下源码所示:

struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t src); /* 源端口 */
PACK_STRUCT_FIELD(u16_t dest); /* 目的端口 */
PACK_STRUCT_FIELD(u32_t seqno); /* 序号 */
PACK_STRUCT_FIELD(u32_t ackno); /* 确认序号 */
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); /* 首部长度+保留位+标志位 */
PACK_STRUCT_FIELD(u16_t wnd); /* 窗口大小 */
PACK_STRUCT_FIELD(u16_t chksum); /* 校验位 */
PACK_STRUCT_FIELD(u16_t urgp); /* 紧急指针 */
} PACK_STRUCT_STRUCT;

        可见, lwIP 使用 tcp_hdr 结构体描述 TCP 首部各个字段,值得注意的是,该结构体的_hdrlen_rsvd_flags 变量用来描述下图黄色部分的内容。

1.6 lwIP 的 TCP 连接状态图

发送端与接收端发送的指令会进入不同的状态, 因此, lwIP 在 tcpbase.h 文件中定义了枚举类型 tcp_state,它是用来描述 TCP 的状态,该枚举tcp_state 如下源码所示:

enum tcp_state {
CLOSED = 0, /* 关闭状态 */
LISTEN = 1, /* 监听状态 */
SYN_SENT = 2, /* 发送请求连接 */
SYN_RCVD = 3, /* 接收请求连接 */
ESTABLISHED = 4, /* 连接状态已建立 */
FIN_WAIT_1 = 5, /* 程序已关闭该连接 */
FIN_WAIT_2 = 6, /* 另一端已关闭连接 */
CLOSE_WAIT = 7, /* 等待程序关闭连接 */
CLOSING = 8, /* 两端同时收到对方的关闭请求 */
LAST_ACK = 9, /* 服务器等待对方接收关闭操作 */
TIME_WAIT = 10 /* 关闭成功 */
}

如果 TCP 需要建立连接,则系统需要三次握手;如果 TCP 中断连接,则系统需要四次挥手。

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

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

相关文章

算法导论 总结索引 | 第三部分 第十四章:数据结构的扩张

1、通过存储 额外信息的方法来扩张一 种标准的数据结构,然后对这种数据结构,编写新的操作来支持所需的应用。因为添加的信息 必须要能被该数据结构上的常规操作更新和维护 2、通过扩张红黑树构造出的两种数据结构:14.1介绍 一种支持一般动态…

js 数字精确度

事情的起源: 项目中 填写的赔付金额是小数 传给后端需要 *100 9.87 *100 传给后端后是986.9999999999999 后端直接取整 就变成了9.86了 0.1 0.2 ! 0.3 console.log(0.1 0.2) //0.30000000000000004 console.log(0.1 0.2 0.3) //false1. 数字的存储 浮点数是用…

全新STC12C5A60S2单片机+LCD19264大屏万年历农历生肖节气节日显示+闹钟+温湿度+台灯

资料下载地址:全新STC12C5A60S2单片机LCD19264大屏万年历农历生肖节气节日显示闹钟温湿度台灯 这是旧版 退役拆解了 新版 与电路图所示 共设置4个按键 短按开关台灯 加减键调光 长按进入菜单 1.台灯 加入PCA PWM 调光 STC12C5A60S2的PCA PWM非常好用 设置简单无极…

Java面试题:解决Redis缓存击穿问题

缓存击穿 当一个key过期时,需要对这个key进行数据重建 在重建的时间内如果有大量的并发请求进入,就会绕过缓存进入数据库,会瞬间击垮DB 重建时间可能因为数据是多个表的混合结果需要分头统计而延长,从而更容易出现缓存击穿问题 缓存击穿的解决方案 添加互斥锁 先查询缓存…

实验八、地址解析协议《计算机网络》

水逆退散,学业进步,祝我们都好,不止在夏天。 目录 一、实验目的 二、实验内容 (1)预备知识 (2)实验步骤 三、实验小结 一、实验目的 完成本练习之后,您应该能够确定给定 IP 地…

数仓建模—ChatETL

数仓建模—ChatETL 前面我们介绍过ChatBI ,就是让用户通过自然语言对话的方式可以获取到自己想要的数据,然后通过合适的报表展示出来,其实我们可以将其理解为应用层面的技术创新,但是这个实现的前提就是我们底层已经有加工好的大量的数据模型数据表,并且有完善的元数据建…

python中文件操作详解(1)

在python中我们经常会对文件进行一些常见的操作,比如打开文件,操作文件,关闭文件,此篇文章主要是记录自己在学习过程中的一些总结供大家学习,也欢迎查漏补缺~ 1.文件的打开 方式一:此种方式打开的文件需要…

SQL实验 连接查询和嵌套查询

一、实验目的 1.掌握Management Studio的使用。 2.掌握SQL中连接查询和嵌套查询的使用。 二、实验内容及要求(请同学们尝试每道题使用连接和嵌套两种方式来进行查询,如果可以的话) 1.找出所有任教“数据…

云计算如何助力金融科技企业实现高效运营

一、引言 随着信息技术的飞速发展,云计算作为一种新兴的计算模式,正在逐渐改变着传统金融行业的运营模式。金融科技企业作为金融行业的重要组成部分,面临着日益增长的业务需求和技术挑战。在这一背景下,云计算凭借其弹性扩展、高可用性、低成本等优势,成为金融科技企业实…

7、架构-架构的安全性

即使只限定在“软件架构设计”这个语境下,系统安全仍然是一 个很大的话题。我们谈论的计算机系统安全,不仅仅是指“防御系统 被黑客攻击”这样狭隘的安全,还至少应包括(不限于)以下这些问 题的具体解决方案。 认证&am…

【Linux多线程】LWP和pthread_t

文章目录 LWPclone系统调用查看线程LWP理解LWP与TID pthread_id LWP LWP是Linux中线程的具体实现形式,在linux中,进程和线程本质上都是相同的,都是通过task_struct结构体来表示的。LWP是内核级线程,TID是其唯一标识符&#xff0c…

深度网络学习笔记(一)——self-attention机制介绍和计算步骤

self-attention机制介绍及其计算步骤 前言一、介绍和意义二、 计算细节2.1 计算Attention Score2.2 计算value2.3 计算关联结果b2.4 统一计算 三、总结 前言 Transformer是一种非常常见且强大的深度学习网络架构,尤其擅长处理输出为可变长度向量序列的任务&#xf…

杂项——STM32ZET6要注意的一些问题——高级定时器问题和PB3,PB4引脚问题

ZET6可能会用到定时器,高级定时器要输出PWM要加上这样一行代码,否则无法正常输出PWM波 TIM_CtrlPWMOutputs(TIM8, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要 ZET6中PB3,PB4引脚默认功能是JTDO和NJTRST,如果想将…

python基础篇(2):字符串扩展知识点

1 字符串的三种定义方式 字符串在Python中有多种定义形式: (1)单引号定义法 name 博主帅绝上下五千年 print(name) print(type(name)) 效果如下: (2)双引号定义法 name "博主帅绝上下五千年&qu…

代课老师可以评职称吗?

代课老师可以评职称吗?这个问题颇具争议。代课老师由于其工作性质的特殊性,往往处于职称评审的边缘地带 代课老师,承担着临时或短期的教学任务,填补因各种原因造成的教师空缺。他们的工作性质决定了他们与正式教师在职责和角色上存…

【uni-app】开发问题汇总

文章目录 1、APP获取dom2、添加页面,参考其他页面,国际化就是对应页面的导航的国际化"navigationBarTitleText": "%m.i.ForgetPaymentPassword.bartitle%",3、setStatusBarStyle这个导航栏设置方法不要了,导航栏现在都用…

66、API攻防——接口安全阿里云KEYPostmanDVWS

文章目录 一、工具使用——Postman自动化测试二、安全问题——Dvws泄露&鉴权&XXE三、安全问题——阿里KEY信息泄露利用 dvws-node 一、工具使用——Postman自动化测试 二、安全问题——Dvws泄露&鉴权&XXE 路径中出现/api/,一般都是接口。 请求包是…

Cesium项目报错An error occurred while rendering. Rendering has stopped.

一般就是本地打开会报错,改成用本地服务器打开 全局安装一个live-server sudo cnpm i live-server -g然后新增一个package.json文件 npm init -y然后在package.json的scripts中增加一个命令 "server": "live-server ./ --port8181 --hostlocalhos…

香橙派 AIpro 的系统评测

0. 前言 你好,我是悦创。 今天受邀测评 Orange Pi AIpro开发板,我将准备用这个测试简单的代码来看看这块开发版的性能体验。 分别从:Sysbench、Stress-ng、PyPerformance、RPi.GPIO Benchmark、Geekbench 等方面来测试和分析结果。 下面就…

第15章 面向服务架构设计理论实践

服务是一个由服务提供者提供的,用于满足使用者请求的业务单元。服务的提供者和使用者都是软件代理为了各自的利益而产生的角色。 在面向服务的体系结构(Service-Oriented Architecture,SOA)中,服务的概念有了延伸,泛指系统对外提供的功能集。…