Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
LWIP
tcp
TCP报文及其在Lwip的实现
发布于 2021-08-03 19:51:23 浏览:1289
订阅该版
[tocm] # LWIP TCP报文基础 TCP协议(Transmission Control Protocol)传输控制协议在LWIP协议栈中占据了大半的代码,它是最常见的传输层协议,也是最稳定的传输层协议,很多上层应用都是依赖TCP协议进程传输数据,如SMTP,FTP等等 ## 1 TCP协议简介 TCP与UDP一样,都是传输层的协议,但是提供的服务却不相同,UDP为上层应用提供的是一种不可靠的,无连接的服务,而TCP提供一种面向连接,可靠的字节传输服务,TCP让两个主机建立连接的关系,应用数据以数据流的形式进行传输,先后发出的数据在网络中虽然也是互不干扰的传输,但是这些数据本身携带的信息确实紧密联系的,TCP协议会给每个传输的字号进行编号,当然了,两个主机方向上的数据编号是彼此独立的,在传输的过程中,发送方把数据的起始编号与长度放在TCP报文中,接收方将所有数据按照编号组装起来,然后返回一个确认,当所有的数据接收完成后才将数据递交到应用层。 ## 2 TCP 报文段结构 TCP 报文段依赖 IP 协议进行发送,因此 TCP 报文段与 ICMP 报文 一样,都是封装在 IP 数据报文中,IP 数据报封装在以太网帧中,因此 TCP 报文段也是经过 了两次的封装,然后发送出去,报文结构如下: ![a.jpg](https://oss-club.rt-thread.org/uploads/20210803/caea57e908137311f0467d264bf6b52e.jpg.webp) 1.源端口(Source Port),16位。 2.目的端口(Destination Port),16位。 3.序列号(Sequence Numbe)发送数据包中的第一个字节的,32位。TCP协议是基于流发送数据的,所有使用序号给发送的所有数据字节都编上号,并按照序号进行顺序发送。 4.确认序列号(Acknowledgment Number),32位。TCP的通信是全双工的(两端同时发送和接受),当连接建立成功后,每一方都能同时发送和接收数据。每一个方向的序号代表这个报文段携带的第一个字节数据的编号。每一方还需要使用确认号对它已经收到的字节进行确认。即:本端把收到的最后一个字节的编号加一,这个值就是确认号,然后发送给对端。 5.数据偏移(Data Offset),4位,该字段的值是TCP首部(包括选项)长度除以4。 6.标志位:6位,URG表示紧急指针(Urgent Pointer)字段有意义,ACK表示确认序(Acknowledgment Number)字段有意义;TCP规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1.PSH表示Push功能,推送数据。RST表示复位TCP连接SYN表示SYN报文,在建立TCP连接的时候使用,用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此, SYN置1就表示这是一个连接请求或连接接受报文。FIN表示没有数据需要发送了,终止连接。在关闭TCP连接的时候使用,用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。 7.窗口(Window)表示接收缓冲区的空闲空间,16位,用来告诉TCP连接对端自己能够接收的最大数据长度。 8.校验和(Checksum),16位。每一个报文段都包括有校验和字段,若报文有损伤,则由终点TCP将其丢弃,并被认为是丢失。TCP的校验和是强制的。 9.紧急指针(Urgent Pointers),16位,只有URG标志位被设值时该字段才有意义,表示紧急数据相对序列号(Sequence Number字段的值)的偏移。用URG值+序号得到最后一个紧急字节。 # LWIP中TCP协议的实现 ## 1.TCP控制块 TCP 报文段如 APR 报文、IP 数据报一样,也是由首部+数据区域组成,TCP 报文段的 首部我们称之为 TCP 首部,其首部内推很丰富,各个字段都有不一样的含义,如果不计算 选项字段,一般来说 TCP 首部只有 20 个字节,具体见上图。在 LwIP 中,报文段首部采用一个名字叫 tcp_hdr 的结构体进行描述。 ```c PACK_STRUCT_BEGIN 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; PACK_STRUCT_END ``` 每个 TCP 报文段都包含源主机和目标主机的端口号,用于寻找发送端和接收端应用线 程,这两个值加上 I P 首部中的源 I P 地址和目标 I P 地址就能确定唯一一个 TCP 连接。 序号字段用来标识从 TCP 发送端向 TCP 接收端发送的数据字节流,它的值表示在这 个报文段中的第一个数据字节所处位置吗,根据接收到的数据区域长度,就能计算出报文 最后一个数据所处的序号,因为 TCP 协议会对发送或者接收的数据进行编号(按字节的形 式),那么使用序号对每个字节进行计数,就能很轻易管理这些数据。序号是 32 bit 的无 符号整数。 当建立一个新的连接时,TCP 报文段首部的 SYN 标志变 1,序号字段包含由这个主机 随机选择的初始序号 ISN(Initial Sequence Number)。该主机要发送数据的第一个字节序 号为 ISN+1,因为 SYN 标志会占用一个序号。 既然 TCP 协议给每个传输的字节都了编号,那么确认序号就包含接收端所期望收到的 下一个序号,因此,确认序号应当是上次已成功收到数据的最后一个字节序号加 1。当然, 只有 ACK 标志为 1 时确认序号字段才有效,TCP 为应用层提供全双工服务,这意味数据能 在两个方向上独立地进行传输,因此确认序号通常会与反向数据(即接收端传输给发送端 的数据)封装在同一个报文中(即捎带),所以连接的每一端都必须保持每个方向上的传输数据序号准确性。 首部长度字段占据 4bit 空间,它指出了 TCP 报文段首部长度,以字节为单位,最大能 记录 15*4=60 字节的首部长度,因此,TCP 报文段首部最大长度为 60 字节。在字段后接下 来有 6bit 空间是保留未用的。 此外还有6bit空间,是TCP报文段首部的标志字段,用于标志一些信息: URG:首部中的紧急指针字段标志,如果是1表示紧急指针字段有效。 ACK:首部中的确认序列字段标志,如果是1表示确认序列字段有效。 PSH:该字段置一表示接收方应该尽快将这个报文段交给应用层。 RST:重新建立TCP连接。 SYN:用同步序列发起连接。 FIN:终止连接。 TCP的流量控制由连接的每一端通过声明的窗口大小来提供,窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的数据序号,发送发根据窗口的大小调整发送数据,以实现流量控制。窗口大小是一个占据16bit空间的字段,因而窗口最大为65535字节,当接收方告诉发送发一个大小为0的窗口时,将完全阻止发送方的数据发送。 检验和覆盖了整个TCP报文段:TCP首部和TCP数据区域,由发送端计算填写,并由接收端进行验证
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
白燕少年
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
{lwip}使能RT_LWIP_DHCP时可以获取到ip
3
stm32f103 LWIP 2.0.2 TCP收发问题
4
lwip2.1不重启修改IP
5
关于网络协议栈的测试
6
可否将LWIP升级到2.1.2 和 2.0.3?
7
socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
8
tcpclient 插拔网线问题?
9
两个tcpclient同时通讯可以吗?
10
SO_BINDTODEVICE 未定义该如何解决
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部